When passing a function console.log() as a parameter to some other function then(), the argument list of console.log() is always ignored
because JavaScript picks up the arg-list of passed function automatically.
(*) e.g. then(console.log): pass the parameters of then to console.log(), so ignore the parentheses.
Error handling with promises
When a promise rejects, the control jumps to the closest rejection handler.
So append .catch to the end of chain to catch all errors.
.then versus .catch
promise.then(f1).catch(f2) vs. promise.then(f1, f2) Are these code fragments equal?
no, they are not equal:
If the promise itself gets rejected, then yes the functions will behave the same and the f2 handlers will handle the error the same.
But if an error occurs within the f1 function itself after the promise has resolved, then only the f2 function inside the catch will handle that error.
The current then() handles the PREVIOUS promise in the chain.
When a promise goes error, throwing in f1 can only be handled by the NEXT chained handler.
rethrowing
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// the execution: catch -> catch newPromise((resolve, reject) => { thrownewError("Whoops!"); }).catch(function(error) { if (error instanceofURIError) { // handle it } else { alert("Can't handle such error"); throw error; // throwing this error jumps to the next catch } }).then(function() { /* doesn't run here */ }).catch(error => { alert(`The unknown error has occurred: ${error}`); // don't return anything => execution goes the normal way });
e.g. download several URLs in parallel and process the content once they are all done.
syntax
let promise = Promise.all([...promises...])
包含n个promise的数组, not just [], any iterable is fine.
If any of those objects is not a promise, it’s passed to the resulting array “as is” (not change).
顺序不变:the order of the resulting array members is the same as in its source promises.
失败仍会执行:If any of the promises is rejected, the promise returned by Promise.all immediately rejects with that error. But the others will still continue to execute, but Promise.all won’t watch them anymore, and their results will be ignored.
Trick
map an array of rough data into an array of promises, and wrap that into Promise.all()
e.g. url = [...]; request = url.map(url => fetch(url)); Promise.all(request)
Promise.allSettled
Promise.all is good for “all or nothing” cases, but for Promise.allSettled just waits for all promises to settle, regardless of the result.
result array
{status:"fulfilled", value:result} for successful responses
{status:"rejected", reason:error} for errors.
Promise.race
返回最快完成的:Waits only for the first(fastest) settled promise and gets its result (or error).
剩下的忽略:all further results/errors are ignored.
syntax
let promise = Promise.race(iterable)
Promise.resolve/reject – old version
Promise.resolve
传入参数为 非Promise类型的对象,则返回 【成功的Promise对象】
传入参数为 Promise类型的对象,则传入参数的结果决定 【resolve返回的结果】
例如:let p = Promise.resolve(521);
Promise.reject
状态永远【失败】,且传入参数是什么就结果就是什么
e.g. thenables and functions we want write loadCached(url).then(...), and guarantee to return a promise.
Microtasks
Microtasks queue
Promise handlers .then.catch.finally are always asynchronous.
改变状态后,回调函数都会执行:So even when a Promise is immediately resolved, the code on the lines below .then.catch.finally will still execute before these handlers.
That’s because:
Execution of a task in this queue is initiated only when nothing else is running.
So when a promise is ready, its handlers are put into the queue; they are not executed yet. When the JavaScript engine becomes free from the current code, it takes a task from the queue and executes it.
改变Promise状态 和 指定回调函数/执行回调函数的顺序
状态改变 / 指定回调函数
Promise包含【异步操作】,先指定回调函数 → 改变状态
Promise【正常操作】,先改变状态 → 指定回调函数
改变状态 / 执行回调函数
只有状态改变后,才执行
Async/await
Async functions, async
async function xxx before a function 返回一个 Promise对象(用Promise.resolve()方法).
return 一个 非Promise类型的数据:【状态】成功 【值】return的值
return 一个 Promise对象:【状态】同 【值】同
throw 抛出异常: 【状态】失败 【值】异常
Await, await
works ONLY inside async functions:
1 2 3
asyncfunctionmain() { let value = await <Promise>; }
await <Promise>: wait until that promise settles and returns its result.
But at the top level of the code, when we’re outside any async function, we’re syntactically unable to use await, so it’s a normal practice to add .then/catch
works well with Promise.all: let results = await Promise.all([...])
asyncfunctionshowAvatar() { // read our JSON let response = awaitfetch('/article/promise-chaining/user.json'); let user = await response.json();
// read github user let githubResponse = awaitfetch(`https://api.github.com/users/${user.name}`); let githubUser = await githubResponse.json();
// show the avatar let img = document.createElement('img'); img.src = githubUser.avatar_url; img.className = "promise-avatar-example"; document.body.append(img);