1. 定义
Promise
对象用于表示一个异步操作的最终完成(或者失败)及其结果值,是异步编程的一种解决方案,比传统的解决方案(回调函数和事件)更合理、更强大。ES6 将其写进了语言标准,统一用法,提供了原生的Promise
对象。
一个Promise
对象代表一个在这个Promise
被创建出来时不一定已知的值,它可以把异步操作最终的成功返回值或失败原因和相应的处理程序关联起来。这样,异步方法并不会立即返回最终的值,而是会返回一个Promise
。
一个Promise
必然处于以下几种状态之一:
pending
:初始状态,未被兑现,也未被拒绝fulfilled
:已兑现,操作完成rejected
:已拒绝,操作失败
2. 基本使用
通过new
操作符来完成Promise
的实例化,需要传入一个函数作为参数。Promise
的状态是私有的,只能在内部进行操作。在传入的函数中,控制Promise
的状态转换是通过调用它的两个函数参数实现的,通常命名为resolve()
和reject()
。调用resolve()
将状态转换为fulfilled
,调用reject()
将状态转换为rejected
。另外,调用reject()
将抛出错误。
如下代码,使用new
操作符实例化了一个Promise
,传入了一个函数,函数有两个参数:resolve()
和reject()
。通过简单的判断,控制Promise
的状态转换。显然,当前代码执行后,应该调用resolve()
,即将状态转化为fulfilled
。
在Promise
后,调用了then
方法,then
方法最多接收两个函数作为参数,第一个参数是状态变为fulfilled
的回调函数,第二个参数是状态变为rejected
的回调函数。本例中,由于Promise
状态已变为fulfilled
,故then
方法执行第一个参数,打印出resolve()
方法传来的值:'fulfilled'
。
new Promise((resolve, reject) => {
const a = 1;
if (a === 1) {
resolve('fulfilled');
} else {
reject('rejected');
}
}).then(
fulfilledValue => console.log(fulfilledValue),
rejectedValue => console.log(rejectedValue)
);
// fulfilled
如果稍微修改一下a
的值,使Promise
的状态转为rejected
,那么then
方法就会执行第二个参数,打印出reject()
方法传来的值:'rejected'
。
new Promise((resolve, reject) => {
const a = 2;
if (a === 1) {
resolve('fulfilled');
} else {
reject('rejected');
}
}).then(
fulfilledValue => console.log(fulfilledValue),
rejectedValue => console.log(rejectedValue)
);
// rejected
另外,如果内部抛出错误,then
方法也会执行第二个函数:
new Promise((resolve, reject) => {
throw 'error';
}).then(null, error => console.log(error));
// error
3. 原型方法
1. Promise.prototype.then()
then()
方法返回一个新的Promise
,如上文所述,它最多需要两个参数:Promise
的成功和失败的回调函数。因为Promise
只能转换一次状态,所以这两个函数一定是互斥的。
then
方法支持链式调用。
返回的新Promise
,具体情况如下,如果then
中的回调函数:
(1)返回了一个值,那么then
返回的Promise
是fulfilled
状态,并将返回的值作为fulfilled
状态的回调函数参数值。
如下代码所示,最初的Promise
状态是fulfilled
,那么第一个then
方法调用第一个回调函数,先打印出1
,又返回了'Jack'
,那么该then
返回的Promise
也是fulfilled
状态,并且将'Jack'
作为第二个then
方法的回调函数参数。
new Promise((resolve, reject) => {
resolve(1);
// reject(-1);
})
.then(value => {
console.log('fulfilledValue', value);
return 'Jack';
})
.then(
res => {
console.log('fulfilledValue', res);
},
res => {
console.log('rejectedValue', res);
}
);
// fulfilledValue 1
// fulfilledValue Jack
这里,如果把最初的Promise
状态改成rejected
,那么就如下代码,第一个then
方法调用的是它的第二个回调函数,这个回调函数返回'Jack'
,是个值,那么这个then
返回的就是fulfilled
状态,并将返回的值作为fulfilled
状态的回调函数参数值,和上文的规则完全一致。
new Promise((resolve, reject) => {
// resolve(1);
reject(-1);
})
.then(
value => {
console.log('fulfilledValue', value);
},
value => {
console.log('rejectedValue', value);
return 'Jack';
}
)
.then(
res => {
console.log('fulfilledValue', res);
},
res => {
console.log('rejectedValue', res);
}
);
// rejectedValue -1
// fulfilledValue Jack
由此可见,then
方法不管调用哪个回调函数,返回Promise
的规则都是一致的。为了方便起见,下文中的最初Promise
都设置为fulfilled
状态。
(2)没有返回任何值,那么then
返回的Promise
是fulfilled
状态,并且fulfilled
状态的回调函数参数值是undefined
。
如下代码所示,由于第一个then
没有返回任何值,所以第二个then
的第一个回调函数的参数是undefined
。
new Promise((resolve, reject) => {
resolve(1);
// reject(-1);
})
.then(value => {
console.log('fulfilledValue', value);
})
.then(
res => {
console.log('fulfilledValue', res);
},
res => {
console.log('rejectedValue', res);
}
);
// fulfilledValue 1
// fulfilledValue undefined
(3)抛出一个错误,那么then
返回的Promise
是rejected
状态,并将抛出的错误作为fulfilled
状态的回调函数参数值。
new Promise((resolve, reject) => {
resolve(1);
// reject(-1);
})
.then(value => {
console.log('fulfilledValue', value);
throw 'Error!';
})
.then(
res => {
console.log('fulfilledValue', res);
},
res => {
console.log('rejectedValue', res);
}
);
// fulfilledValue 1
// rejectedValue Error!
(4)返回一个是fulfilled
状态的Promise
,那么then
返回的Promise
是fulfilled
状态,并且将前面Promise
接受状态的回调函数参数,作为返回的Promise
接受状态的回调函数参数。
如下代码,第一个then
返回了一个fulfilled
状态的Promise
,那么第二个then
会调用第一个回调函数,并且参数是'fulfilled'
。
new Promise((resolve, reject) => {
resolve(1);
// reject(-1);
})
.then(value => {
console.log('fulfilledValue', value);
return Promise.resolve('fulfilled');
})
.then(
res => {
console.log('fulfilledValue', res);
},
res => {
console.log('rejectedValue', res);
}
);
// fulfilledValue 1
// fulfilledValue fulfilled
(5)返回一个是rejected
状态的Promise
,那么then
返回的Promise
是rejected
状态,并且将前面Promise
拒绝状态的回调函数参数,作为返回的Promise
拒绝状态的回调函数参数。
new Promise((resolve, reject) => {
resolve(1);
// reject(-1);
})
.then(value => {
console.log('fulfilledValue', value);
return Promise.reject('rejected');
})
.then(
res => {
console.log('fulfilledValue', res);
},
res => {
console.log('rejectedValue', res);
}
);
// fulfilledValue 1
// rejectedValue rejected
(6)返回一个是pending
状态的Promise
,那么then
返回的Promise
也是pending
状态,并且它最终状态与前面Promise
最终状态相同。同时,它变成最终状态执行的回调函数参数,与前面Promise
变成最终状态执行的回调函数的参数是相同的。
new Promise((resolve, reject) => {
resolve(1);
// reject(-1);
})
.then(value => {
console.log('fulfilledValue', value);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('1秒后出现');
}, 1000);
});
})
.then(
res => {
console.log('fulfilledValue', res);
},
res => {
console.log('rejectedValue', res);
}
);
// fulfilledValue 1
// fulfilledValue 1秒后出现
(7)如果最初的Promise
是rejected
状态,且第一个then
没有第二个函数参数,那么第二个then
就会执行其第二个回调函数,并且参数为最初Promise
的reject
中的参数。
new Promise((resolve, reject) => {
// resolve(1);
reject(-1);
})
.then(value => {
console.log('fulfilledValue', value);
})
.then(null, res => {
console.log('rejectedValue', res);
});
// rejectedValue -1
2. Promise.prototype.catch()
Promise.prototype.catch()
方法用于给Promise
添加拒绝处理程序。这个方法只接收一个参数:onRejected
处理程序。它的行为与调用Promise.prototype.then(undefined, onRejected)
相同。
如下代码,两种等价的写法。
new Promise((resolve, reject) => {
reject('error');
}).catch(error => console.log(error));
// error
new Promise((resolve, reject) => {
reject('error');
}).then(null, error => console.log(error));
// error
3. Promise.prototype.finally()
Promise.prototype.finally()
方法用于给Promise
添加onFinally
处理程序,这个处理程序在Promise
转换为fulfilled
或rejected
状态时都会执行。但onFinally
处理程序不知道Promise
的状态是fulfilled
还是rejected
,所以这个方法主要用于添加清理代码。
new Promise((resolve, reject) => {
console.log('loading start...');
const a = 2;
if (a === 1) {
resolve(1);
} else {
reject(-1);
}
})
.then(value => {
console.log('fulfilled value', value);
})
.catch(error => console.log('error', error))
.finally(() => console.log('loading end...'));
// loading start...
// error -1
// loading end...
4. 实例方法
1. Promise.all()
Promise.all()
方法接收一个Promise
的可迭代类型的输入,并且只返回一个Promise
实例, 那个输入的所有Promise
的resolve
回调的结果是一个数组。简单来说,Promise.all()
用于将多个Promise
实例包装成一个新的Promise
实例。
const promiseArray = [1, 2, 3, 4].map(item => new Promise(resolve => resolve(item)));
console.log(promiseArray);
// [ Promise { 1 }, Promise { 2 }, Promise { 3 }, Promise { 4 } ]
Promise.all(promiseArray).then(res => console.log(res));
// [ 1, 2, 3, 4 ]
2. Promise.race()
Promise.race(iterable)
方法返回一个Promise
,一旦迭代器中的某个Promise
接受或拒绝,返回的Promise
就会接受或拒绝。
const promiseArray = [1, 2, 3, 4].map(item => new Promise(resolve => resolve(item)));
console.log(promiseArray);
// [ Promise { 1 }, Promise { 2 }, Promise { 3 }, Promise { 4 } ]
Promise.race(promiseArray).then(res => console.log(res));
// 1
3. Promise.resolve()
Promise.resolve()
方法返回一个接受状态的Promise
对象。
Promise.resolve(1).then(res => console.log(res));
// 1
4. Promise.reject()
Promise.reject()
方法返回一个带有参数的拒绝状态的Promise
对象。
Promise.reject(-1).then(null, res => console.log(res));
// -1
以上是本人学习所得,若有不妥,欢迎指出交流!
参考:
- 《JavaScript高级程序设计(第4版)》
- 「MDN」
📘📘欢迎在我的博客上访问:
https://lzxjack.top/