- 最好理解的Promise教程 b站课程 --done
- 微信订阅号 promise --done
- 笔记promise 15题 理解 + 做练习 --done
- vue项目里的promise + 接口请求封装
- promise相关面试题梳理
- async、await
注意
想要实现一个 Promise,必须要遵循如下规则:
- Promise 是一个提供符合标准的 then () 方法的对象。
- 初始状态是 pending,能够转换成 fulfilled 或 rejected 状态。
- 一旦 fulfilled 或 rejected 状态确定,再也不能转换成其他状态。
- 一旦状态确定,必须要返回一个值,并且这个值是不可修改的。
原理
Promise 的运转实际上是一个观察者模式,then() 中的匿名函数充当观察者,Promise 实例充当被观察者。
管理多个 Promise 实例
Promise.all() / Promise.race() 可以将多个 Promise 实例包装成一个 Promise 实例,在处理并行的、没有依赖关系的请求时,能够节约大量的时间。
function wait(ms) {
return new Promise(resolve => setTimeout(resolve.bind(null, ms), ms))
}
// Promise.all
Promise.all([wait(2000), wait(4000), wait(3000)])
.then(console.log)
// 4 秒后 [ 2000, 4000, 3000 ]
// Promise.race
Promise.race([wait(2000), wait(4000), wait(3000)])
.then(console.log)
// 2 秒后 2000
Promise 和 async&await
async&await 实际上只是建立在 Promise 之上的语法糖,让异步代码看上去更像同步代码,所以 async&await 在 JavaScript 线程中是非阻塞的,但在当前函数作用域内具备阻塞性质
使用 async&await 的优势
1. 简洁干净
写更少的代码,不需要特地创建一个匿名函数,放入 then() 方法中等待一个响应。
2. 处理条件语句
当一个异步返回值是另一段逻辑的判断条件,链式调用将随着层级的叠加变得更加复杂,很容易让人混淆。使用 async&await 将使代码可读性变得更好。
3. 处理中间值
异步函数常常存在一些异步返回值,作用仅限于成为下一段逻辑的入场券,如果经历层层链式调用,很容易成为另一种形式的 “回调地狱”。
4. Promise.all
对于多个异步返回中间值,搭配 Promise.all 使用能够提升逻辑性和性能。
// async / await & Promise.all
async function foo() {
// ...
const [a, b, c] = await Promise.all([promiseFnA(), promiseFnB(), promiseFnC()])
const d = await promiseFnD()
// ...
}
错误处理
catch(rejectionFn) 其实就是 then(null, rejectionFn) 的别名。
取消一个 Promise
- 想结束一个 Promise 只能通过 resolve 或 reject 来改变其状态
- 或者利用 Promise.race() 的机制来同时注入一个会超时的异步函数(但是 Promise.race() 结束后主程序其实还在 pending 中,占用的资源并没有释放)
- Promise.race([anAsyncFn(), timeout(5000)])
总结
- 每当要使用异步代码时,请考虑使用 Promise。
- Promise 中所有方法的返回类型都是 Promise。
- Promise 中的状态改变是一次性的,建议在 reject() 方法中传递 Error 对象。
- 尽量为所有的 Promise 添加 then() 和 catch() 方法。
- 使用 Promise.all() 去运行多个 Promise。
- 倘若想在 then() 或 catch() 后都做点什么,可使用 finally()。
- 可以将多个 then() 挂载在同一个 Promise 上。
- async (异步)函数返回一个 Promise,所有返回 Promise 的函数也可以被视作一个异步函数。
- await 用于调用异步函数,直到其状态改变(fulfilled or rejected)。
- 使用 async /await 时要考虑上下文的依赖性,避免造成不必要的阻塞。