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
COMP6080 22T1 - Async - Promises
By haydensmith
COMP6080 22T1 - Async - Promises
- 493