Professional JavaScript for Web Developers 第四版學習筆記 CHAPTER 11: Promises and Async Functions
Introduction to Asynchronous Programming 392
Synchronous vs. Asynchronous JavaScript 392
Legacy Asynchronous Programming Patterns 393
Returning Asynchronous Values 393
Handling Failure 394
Nesting Asynchronous Callbacks 394
Promises 395
The Promises/A+ Specification 395
Promise Basics 395
The Promise State Machine 396
Resolved Values, Rejection Reasons, and Utility of Promises 396
Controlling Promise State with the Executor 397
Promise Casting with Promise.resolve() 398
Promise Rejection with Promise.reject() 399
Synchronous/Asynchronous Execution Duality 399
Promise Instance Methods 400
Implementing the Thenable Interface 400
Promise.prototype.then() 400
Promise.prototype.catch() 403
Promise.prototype.finally() 404
Non-Reentrant Promise Methods 405
Sibling Handler Order of Execution 407
Resolved Value and Rejected Reason Passing 408
Rejecting Promises and Rejection Error Handling 408
Promise Chaining and Composition 410
Promise Chaining 410
Promise Graphs 413
Parallel Promise Composition with Promise.all() and Promise.race() 414
Serial Promise Composition 416
Promise Extensions 418
Promise Canceling 418
Promise Progress Notifications 419
Async Functions 421
Async Function Basics 422
The async keyword 422
The await keyword 424
Restrictions on await 426
Halting and Resuming Execution 427
Strategies for Async Functions 430
Implementing Sleep() 430
Maximizing Parallelization 431
Serial Promise Execution 434
Stack Traces and Memory Management 434
Summary 435
-------------------------------------------------
Promise
let p = new Promise((resolve, reject) => {
resolve();
reject(); // No effect
});
setTimeout(console.log, 0, p); // Promise <resolved>
.then(onResolved,onRejected),.catch(onRejected),.finally(onFinally)
-------------------------------------------------
Promise.all(),Promise.race()
The Promise.all() static method creates an all-or-nothing promise that resolves only once every promise in a collection of promises resolves.
The Promise.race() static method creates a promise that will mirror whichever promise inside a collection of promises reaches a resolved or rejected state first.
-------------------------------------------------
reduce
function addTwo(x) {return x + 2;}
function addThree(x) {return x + 3;}
function addFive(x) {return x + 5;}
function compose(...fns) {
return (x) => fns.reduce((promise, fn) => promise.then(fn), Promise.resolve(x))
}
let addTen = compose(addTwo, addThree, addFive);
addTen(8).then(console.log); // 18
-------------------------------------------------
ES7’s async/await
It introduces a logical extension of asynchronous behavior into the domain of JavaScript functions by introducing two new keywords, async and await.
In an async function, whatever value is returned with the return keyword (or undefined if there is no return) will be effectively converted into a promise object with Promise.resolve(). An async function will always return a promise object. Outside the function, the evaluated function will be this promise object.
async function foo() {
console.log(1);
return 3;
}
// Attach a resolved handler to the returned promise
foo().then(console.log);
console.log(2);
// 1
// 2
// 3
----------------
The await keyword (which is used to pause execution while waiting for a promise to resolve) will attempt to “unwrap” the object’s value, pass the value through to the expression, and asynchronously resume execution of the async function.
The await keyword must be used inside an async function; it cannot be used in a top-level context such as a script tag or module.
The key to fully understanding the await keyword is that it doesn’t just wait for a value to become available. When the await keyword is encountered, the JavaScript runtime can track exactly where the execution was paused. When the value to the right of await is ready, the JavaScript runtime will push a task on the message queue that will asynchronously resume execution of that function.