在 Node.js 的util 模块中存在着util.promisify()
方法,它接收一个遵循常见的错误优先的回调风格的函数作为最后一个参数,并返回一个 promise 版本。
该方法的好处就是将原来的回调风格的函数转变成 Promise 风格的函数,简化了一部分代码,但局限性就是该方法只能在 Node 环境下的 util 模块使用。
这形容词有点多了呀,什么意思呢?其实,就是把使用 fs 模块操作文件的代码(错误优先的函数)传入进去作为参数,fs.readFile('文件名', (err, data)=>{ ... })
,error 参数在前,这种就叫做错误优先。
Promise 的状态(面试知识点)
Promise 的状态:Promise 实例对象中的一个属性 => PromiseState
Promise 的状态分为 3 种:
- 处于pending 状态(等待或未完成) => 实例化 Promise 后
- 处于fulfilled/resolved 状态(已成功) => 执行 resolve()后
- 处于rejected 状态(已失败) => 执行 reject()后
注意:Promise 的状态一旦发生变化,就不会再改变了!
且状态改变只能是从 pending -> fulfilled/resolved或者pending -> rejected
Promise 对象的值:Promise 实例对象中的另一个属性 => PromiseResult,其保存的是异步任务成功或失败的结果。
如何更改值?只能通过 resolve()和 reject()修改。
知道了结果保存的地方,那么再来梳理一下整个流程:
首先,实例化 Promise 对象,导致对象中的 PromiseState 属性的值为 pending => 执行 resolve 方法或 reject 方法并传入执行成功或失败的结果 => 当执行成功或失败后,PromiseResult 属性保存了相应的结果作为值 => 调用 then 方法,将 PromiseResult 属性的值取出来进行下一步处理,同时返回一个新的 Promise 对象。
Promise 相关API
(面试知识点)
-
Promise 构造函数:Promise(executor) { … }
(1)executor 函数:执行器函数 (resolve, reject) => { … }
(2)resolve 函数:内部定义成功时我们调用的函数,value => { … }
(3)reject 函数:内部定义失败时我们调用的函数,reason => { … }
注意:executor 函数会在 Promise 内部立即同步调用,异步操作在执行器函数中进行。
-
Promise.prototype.then
方法:(onResolved, onRejected
) => { … }
(1)onResolved
函数:成功时的回调函数,value => { … }
(2)onRejected
函数:失败时的回调函数,reason => { … }
(3)不管是成功时的回调函数还是失败时的回调函数,都将返回一个新的 Promise 对象
-
Promise.prototype.catch
方法:onRejected
=> { … }
(1)onRejected
函数:失败时的回调函数,reason => { … }
(2)catch 方法只能在 Promise 实例对象处于 rejected 状态下,才能捕捉错误,其内部也是由 then 方法实现的。
-
Promise.resolve
方法:value => { … }
(1)value: 成功的数据或 Promise 对象
(2)同时**返回一个成功/**失败的 Promise 对象
-
Promise.reject
方法:reason=> { … }
(1)reason: 失败的原因
(2)返回一个失败的 Promise 对象
-
Promise.all
方法:promises => { … }
(1)promises: 包含 n 个 promise 的数组
(2)返回一个新的 promise,只有所有的 promise 都成功才成功,只要有一个失败了就直接失败
-
Promise.race
方法:promises => { … }
(1)promises: 包含 n 个 promise 的数组
(2)返回一个新的 promise,第一个完成的 promise 的结果状态就是最终的结果状态
Promise 关键问题
A. 如何改变 Promise 的状态?
1.resolve():pending -> fulfilled/resolved
2.reject():pending -> rejected
3.抛出异常 throw:如果当前是 pending 就会变为 rejected
B. 一个 Promise 指定多个成功/失败回调函数,都会调用吗?
当 promise 改变为对应状态时都会调用
C. 改变 promise 状态和指定回调函数谁先谁后?
1.都有可能,正常情况下是先指定回调再改变状态,但也可以先改变状态再指定回调
2.如何先改变状态再执行回调?
(1)在执行器函数中直接调用 resolve()、reject(),因为执行器函数会在 Promise 内部立即同步调用,因此会导致先改变状态后指定回调。
(2)延迟更长时间才调用 then()
3.什么时候才能得到数据?
(1)如果先指定的回调,那只有当状态发生改变时,才能调用回调函数,进而得到数据
(2)如果先改变的状态,那当指定回调时,就会调用回调函数,进而得到数据
(3)总之就是:在执行器函数中可以进行同步/异步操作,但只有当状态发生改变时,才能调用回调函数,然后得到数据。
D. promise.then()返回的新 promise 的结果状态由什么决定?
(1)由then()指定的回调函数执行的结果决定
(2)详细说明:
E. promise 如何串连多个操作任务?
由于 then()返回的是一个新的 promise 对象,因此可以使用then 的链式调用串连多个同步/异步任务。
F. Promise 的异常穿透?
G. 中断 Promise 链?
手写(自定义)Promise(面试知识点)