COMP6080

Web Front-End Programming

Javascript - Async

Promises

 

Credit to Simon Haddad for being a key part of preparing this lecture

What we know

Javascript, unlike languages like Python or C, has asynchronicity built in by default.

 

That means things tend to be async by default, and we have to work around this, like we did when we learned about callbacks.

 

Let's review callbacks

  • Look at chapters-callback-linear.js:
    • How async JS works through use of callbacks
  • Look at chapters-callback-nested.js:
    • How to control async JS through callback nesting

Promises: An evolution of callbacks

Promises, like callbacks, assist us to manage delayed completion of blocking code (file I/O, network I/O, etc)

 

Promises provide us with the same problem-solving environment as a callback pattern, but with substantially more powerful capabilities and a syntax capable of cleaner code.

 

Let's do a direct comparison of our callback and promise code.

Type Callback Promise
Linear chapters-callback-linear.js chapters-promises-linear.js
Nested chapters-callback-nested.js chapters-promises-nested.js

How are these promises written?

Let's learn about how to turn a fileRead standard callback function into a promise. This involves understanding the structure of a promise.

 

Constructor:

  • Accepts a callback that takes resolve() and reject() functions
  • Fulfillment = calling resolve()
  • Rejection = calling reject()

.then:

  • Most common way to chain promises.
  • Executes the next action if the previous one fulfilled

.catch:

  • Catch-all error handler for the chain above

How are these promises written?

Let's learn about how to turn a fileRead standard callback function into a promise. This involves understanding the structure of a promise.

 

A promise has a few possible states:

  • Pending: Not evaluated (still processing)
  • Settled: Either rejected or fulfilled
    • Fulfilled: Done! Call resolve()
    • Rejected: Error! Call reject()

 

Promise Chaining

Promises can be chained together to enforce order of processing and ensure clear and concise syntax. This is shown in chapters-promises-nested-clean.js

 

  • Nested execution of dependent operations
  • Each .then() runs iff the previous promise fulfilled
  • Any error/rejection that happens passed to the next-nearest .catch()
  • After a .catch(), more operations can occur
  • Every .then() returns a new promise which wraps the previous one.
    • Even if the given callback doesn’t return a promise.
    • Stored as Russian dolls
      • But executed as a stack i.e. most-nested happens first

Promise Branching

Branching promises allow you to control what is processed concurrently and what is processed linearly

 

  • Multiple .then()’s on the same promise = branching
  • When the parent promise is resolved, all .then()’s invoked in order
  • Allows for complex control-flow on fulfillment

Promise Error Handling

Mostly error handling is quite straightforward, but there are a few extra details worth considering.

  • Errors/Exceptions always cause rejections
  • Explicit rejections done via calling reject()
  • Any exceptions cause an implicit rejection
  • .catch() clauses can handle errors or pass them to the next .catch() by rethrowing
  • .finally() is also available that will run regardless of if an error occurred or not

Promise Orchestration

The Promise class has some utilities for easy orchestration

  • Promise.all(): returns a promise that resolves iff all of the promises passed to it resolve
  • Promise.allSettled(): returns a promise that resolves once all of the promises passed to it are resolved
  • Promise.any(): returns a promise that resolves if at least one of the promises passed to it resolves
  • Promise.race(): returns a promise which resolves as soon as one of the promises passed to it resolves
  • Promise.reject(): immediately return a rejected promise with a value
  • Promise.resolve(): immediately return a resolved promise with a value

Feedback

Made with Slides.com