详细内容参考链接: ECMAscript入门.
http://es6.ruanyifeng.com/#docs/promise.
基础
new Promise()
内部的函数是同步任务..then()
、.cath()
内部都是异步执行,所以会在同步任务全部执行完之后才会调用..then()
方法指定的回调函数,如果运行中抛出错误,也会被.catch()
方法捕获..catch()
等同于.then(null/undefined, () => {})
- Promise状态不可逆如果 Promise 状态已经变成resolved,再抛出错误是无效的。因为 Promise 的状态一旦改变,就永久保持该状态,不会再变了。
- Promise 内部的错误不会影响到 Promise 外部的代码,通俗的说法就是“Promise 会吃掉错误”。Node.js未来会修复
Promose.prototype.finally()
.finally()
表示不管异常与否, 必定执行(ES2018).finally()
方法的回调函数不接受任何参数,这意味着没有办法知道,前面的 Promise 状态到底是fulfilled还是rejected。这表明,finally方法里面的操作,应该是与状态无关的,不依赖于 Promise 的执行结果。finally()
本质上是then方法的特例。finally()
方法总是会返回原来的值。
Promise.resolve(2).finally((res) => { // 这里拿不到值
console.log(res); // undefined
})
.then(res => { // 拿到的是.finally()之前的原来的值
console.log(res); // 2
})
Promise.all([p1, p2, p3, …])
Promise.all([p1, p2, p3])
如果p1,p2,p3不是Promise实例就会先调Promise.resolve()
方法,将参数转为 Promise 实例- 只有p所有Promise实例的状态都变成fulfilled(成功),
Promiose.all()
的状态才会变成fulfilled,此时p返回值组成一个数组,传递给p的回调函数。只要p之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给Promise.all()
的回调函数。
const p= [
new Promise((resolved, rejected) => { resolved(1) }),
new Promise((resolved, rejected) => { resolved(2) }),
]
Promise.all(p).then((result) => { // 都成功数组返回Promise实例的值
console.log(result); // [1, 2]
}).catch((err) => { // 出错就返回第一个出错的Promise实例值
console.log('错在' + err);
});
- 如果作为参数的 Promise 实例,自己定义了catch方法,那么它一旦被rejected,并不会触发
Promise.all()
的catch()
方法。
const test = [
new Promise((resolved, rejected) => {
resolved(1)
}),
new Promise((resolved, rejected) => {
rejected(2)
}).catch(err => { // 我捕获我自己的错误
console.log(err)
})
]
Promise.all(test).then((result) => { // resolved 找不到第二个Promise实例的错误
console.log(result); // 它自己捕获了自己的错
}).catch((err) => {
console.log('错在' + err);
});
Promise.race([p1,p2,p3])
Promise.race([p1,p2,p3])
如果有一个改变成resolved或者rejected就执行Promise.race()之后的.then
或catch
与Promise.all()很像, 也会有转换参数成Promise实例
Promise.allSettled([p1,p2,p3]) ES2020
Promise.allSettled([p1,p2,p3])
接收一个Promise实例数组,无论数组中的实例变成resolved
或rejected
最终Promise.allSettled()
都将执行resolved
,并且返回值是一个数组- 返回的数组的每个成员都是一个对象,对应传入
Promise.allSettled()
的所有Promise 实例
。每个对象都有status
属性,该属性的值只可能是字符串fulfilled或字符串rejected。fulfilled时,对象有value属性,rejected时有reason属性,对应两种状态的返回值。
const test = [
new Promise((resolved, rejected) => {resolved(1)} ),
new Promise((resolved, rejected) => {rejected(2)} )
]
Promise.allSettled(test).then((result) => { // 无论对错, 都会成功执行resolved()
console.log(result);
// [
// { status: 'fulfilled', value: 1 },
// { status: 'rejected', reason: 2 }
// ]
}).catch((err) => {
console.log('错在' + err);
});
Promise.resolve()
- Promise.resolve() 将现有对象转换成Promise对象
Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))
参数是一个 Promise 实例
- 如果参数是 Promise 实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例。
参数是一个thenable
对象
thenable
对象指的是具有then
方法的对象,比如下面这个对象。
// Promise.resolve方法会将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法。
let thenable = {
then: function(resolve, reject) {
resolve(42);
}
};
let p1 = Promise.resolve(thenable); // 执行thenable内的then方法
p1.then(function(value) { // 因为调用了resolved()自然进入到.then()中
console.log(value); // 42
});
- 上面代码中,thenable对象的then方法执行后,对象p1的状态就变为resolved,从而立即执行最后那个then方法指定的回调函数,输出 42。
参数不是具有then方法的对象,或根本就不是对象
- 如果参数是一个原始值,或者是一个不具有
then
方法的对象,则Promise.resolve方法返回一个新的Promise 对象
,状态为resolved
。
const p = Promise.resolve('Hello');
p.then(function (s){
console.log(s)
});
// Hello
- 上面代码生成一个新的
Promise 对象
的实例p。由于字符串Hello不属于异步操作(判断方法是字符串对象不具有then
方法),返回 Promise 实例的状态从一生成就是resolved
,所以回调函数会立即执行。Promise.resolve
方法的参数,会同时传给回调函数。
不带有任何参数
Promise.resolve()
方法允许调用时不带参数,直接返回一个resolved
状态的Promise 对象
。
所以,如果希望得到一个Promise 对象
,比较方便的方法就是直接调用Promise.resolve()
方法。
const p = Promise.resolve();
p.then(function () { // resolved状态
// ...
});
- 上面代码的变量p就是一个 Promise 对象。
- 需要注意的是,立即
resolve()
的Promise 对象
,是在本轮“事件循环”(event loop)的结束时执行,而不是在下一轮“事件循环”的开始时。
setTimeout(function () {
console.log('three');
}, 0);
Promise.resolve().then(function () {
console.log('two');
});
console.log('one');
// one
// two
// three
- 上面代码中,setTimeout(fn, 0)在下一轮“事件循环”开始时执行,
Promise.resolve()
在本轮“事件循环”结束时执行,console.log(‘one’)则是立即执行,因此最先输出。
Promise.reject()
Promise.reject(reason)
方法也会返回一个新的 Promise 实例,该实例的状态为rejected
。
const p = Promise.reject('出错了');
// 等同于
const p = new Promise((resolve, reject) => reject('出错了'))
p.then(null, function (s) {
console.log(s) // 出错了
});
- 上面代码生成一个
Promise 对象
的实例p,状态为rejected
,回调函数会立即执行。 - 注意,Promise.reject()方法的参数,会原封不动地作为reject的理由,变成后续方法的参数。这一点与Promise.resolve方法不一致。
const thenable = {
then(resolve, reject) {
reject('出错了');
}
};
Promise.reject(thenable)
.catch(e => {
console.log(e === thenable)
})
// true
- 上面代码中,
Promise.reject
方法的参数是一个thenable对象,执行以后,后面catch
方法的参数不是reject
抛出的“出错了”这个字符串,而是thenable对象。也就是说他不会执行thenable对象的.then()
方法