前言
网上关于Promise的文章确实是非常多了,但是自己实践的并不多,这里是针对自己的一个知识点小结和梳理,当然啦如果有错误欢迎提出^_^。
初定义
定义:Promise对象用于一个异步操作的最终完成/失败及其结果值的表示。
使用原因:避免回调嵌套层次过多。
拥有状态:
- pending:初始/未定状态,初始化Promise时,调用executor函数后的状态。
- fulfilled:成功状态。
- rejected:失败状态。
状态转化:
- pending -> fulfilled:操作成功
- pending -> rejected:操作失败
状态转化是单向的,不可逆转。
最基本用法:
可以看到创建一个Promise实例,传入的参数是一个函数,这个函数称为executor/执行器。
new Promise((resolve, reject) => {
if (success) {
resolve(a) // pending to resolved
} else {
reject(err) // pending to rejectd
}
})
方法
而Promise对象本身,有一些方法:
- race()
- reject()
- resolve()
- all()
查看Promise的原型,发现它内置有几个方法:
- catch()
- finally()
- then()
Promise.prototype.then()
- 参数:处理成功的函数,处理错误的函数
- 返回值:返回一个Promise对象,所以可以链式调用。
promise.then(
() => { console.log('我是成功后被执行的') },
() => { console.log('我是失败后被执行的') })
Promise.prototype.catch()
- 参数:捕捉的错误/reject()传来的参数
- 返回值:返回一个Promise对象,所以可以链式调用。
- Promise和then()中抛出错误能够不断传递,就能够在下一个catch()中统一处理,所以一般省略then中的第二个失败执行的函数。
promise.then(
() => { console.log('我是成功后被执行的') }
).catch(
(err) => { console.log(err) })
使用rejects()方法改变状态和抛出错误 throw new Error() 的作用是相同的
Promise.all()
- 参数:可迭代参数,如:数组。
- 用途:处理一些并发的异步操作,需要保证每个都执行完毕。
- 结果:状态全为fulfilled->fulfilled,否则->rejected。
Promise.race()
- 参数:可迭代参数,如:数组。
- 用途:处理一些并发的异步操作,只需要其中一个执行完毕。
- 结果:所有异步操作中有一个状态先改变,就采纳那个最先改变的状态为结果。
Promise.resolve()
- 参数:普通值、Promise对象、带有then的对象。
- 结果:一般情况返回一个状态为fulfilled的Promise对象。解析发生错误则返回rejected的Promise对象。
Promise.resolve('success')
// 其中[[PromiseStatus]]:"resolved"
Promise.reject('fail')
// 其中[[PromiseStatus]]:"rejected"
Promise.resolve(Promise.reject('fail'))
// 其中[[PromiseStatus]]:"rejected"
由这个例子可以看出浏览器认为resolved
和fulfilled
是等价的,但Promise.resolve()
不一定让promise最终是fulfilled
。所以对于resolved
本身和fulfilled
的区别,可以理解为resolved
等价于compiled
,即可能是成功也可能是失败。
Promise.reject()
- 参数: 发生异常的原因。
- 结果:返回一个rejected状态的Promise对象。
注意点
状态变化
- Promise状态只会改变一次。
- 构造函数中的resolve()/reject()只有第一次执行有效,多次调用没有作用。
- Promise状态改变,并且传递了一个值,后续调用.then()/.catch()都可直接拿到该值。
参数/返回值
- .then()/.catch()的参数应该是函数,传入非函数则会发生值穿透。
Promise.resolve(1)
.then(2)
.then(Promise.resolve(3))
.then(console.log) //1
- .then()/.catch()不能返回Promise本身,会造成死循环。
- .then()/.catch()中return一个error对象并不会抛出错误,所以无法捕捉。
因为返回任意一个非Promise 的值都会被包裹成Promise对象,即 return new Error('error!!!')等价于return Promise.resolve(new Error('error!!!'))
执行顺序
- Promise构造函数是同步执行的,resolve()/reject()后的代码也会执行。Promise.then()中的函数是异步执行的。**
以下输出:1243
const promise = new Promise((resolve, reject) => {
console.log(1)
resolve()
console.log(2)
})
promise.then(() => {
console.log(3)
})
console.log(4)
-
process.nextTick
和promise.then
属于microtask
,setImmediate
属于macrotask
。在每一次事件循环中,macrotask只会提取一个执行,而microtask会一直提取,直到microsoft队列为空为止。
以下输出:end nextTick then setTimeout1 setTimeout2
process.nextTick(() => {
console.log('nextTick')
})
setTimeout(() => {
console.log('setTimeout1')
})
Promise.resolve()
.then(() => {
console.log('then')
})
setTimeout(() => {
console.log('setTimeout2')
})
console.log('end')
补充:
macrotasks:
- setTimeout
- setInterval
- setImmediate
- requestAnimationFrame
- I/O
- UI rendering
microtasks:
- process.nextTick
- Promises
- Object.observe
- MutationObserver
参考文章
ES6关于Promise的用法
Promise 必知必会(十道题)
javascript中的异步 macrotask 和 microtask 简介
Tasks, microtasks, queues and schedules
Difference between microtask and macrotask within an event loop context
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。