JavaScript Promise
一、Promise简介
Promise对象表示一个异步操作的最终状态(完成或失败),以及其返回的值。
1、语法
//new Promise(executor)
new Promise(function(resolve, reject){
});
参数executor
是带有resolve
和reject
两个参数的函数,该函数在Promise构造函数执行时调用(executor
函数在Promise
构造函数返回新建的对象前被调用)。resolve
和reject
函数被调用时,分别将promise
的状态改为fulfilled
(完成)或rejected
(失败)。
executor
函数内部通常会执行一些异步操作,操作完成后可以调用resolve
函数来将promise
状态改成fulfilled
,或者在发生错误时将它的状态改为rejected
(此时executor
函数的返回值将被忽略)。
2、状态
一个Promise
对象有以下几种状态:
-
pending
(待定)初始状态,不是成功也不是失败状态。
-
fulfilled
或resolved
(完成)表示操作成功完成。
-
rejected
(失败)表示操作失败。
二、方法
1、原型方法
Promise.prototype.then(onFulfilled, onRejected)
var p = new Promise(function(resolve, reject){
//...
});
p.then(function(value){
//fulfillment
}, function(reason){
//rejection
});
给当前Promise
对象添加完成和失败时的回调函数,并返回新的Promise
对象;该函数可以被链式调用。
第一个参数为Promise
对象变为fulfilled
状态时的回调函数,该函数有一个参数,其值为Promise
对象完成时的值;第二个参数为Promise
对象变为rejected
状态时的回调函数,该函数也有一个参数,其值为Promise
对象失败时的原因。
let p = new Promise((resolve, reject) => {
resolve('Success!');
});
p.then((value)=>{
console.log(value);//Success!
}, (reason)=>{
console.log(reason);
});
let p = new Promise((resolve, reject) => {
reject('Error!');
});
p.then((value)=>{
console.log(value);
}, (reason)=>{
console.log(reason);//Error!
});
catch()
Promise.prototype.catch(onRejected)
var p = new Promise(function(resolve, reject){
//...
});
p.catch(function(reason){
//rejection
});
此方法返回一个新的Promise
对象,是处理失败时的情况,与Promise.prototype.then(undefined, onRejected)
类似。
此方法的参数为当Promise
对象的状态变为rejected
时的回调函数,该函数有一个参数,其值为失败的原因。
如果onRejected
函数抛出一个错误或返回一个rejected
状态的Promise
对象,则返回的Promise
对象是被拒绝的rejected
;否则,是被处理的resolved
。
let p = new Promise((resolve, reject)=>{
resolve('Success');
});
p.then((value)=>{
console.log("√", value);
throw 'ERROR';
}).catch((reason)=>{
console.log("×", reason);
}).then((value)=>{
console.log('after a catch the chain is restored!');
}, (reason)=>{
console.log('Not fired due to the catch');
});
输出:
√ Success
× ERROR
after a catch the chain is restored!
在异步函数中抛出的错误不会被catch()
捕获到:
let p = new Promise((resolve, reject) => {
setTimeout(()=>{
throw 'Uncaught Exception!';
}, 1000);
});
p.catch(reason=>{
console.log('Will not be executed');
});
在resolve()
后面抛出的错误也会被忽略:
let p = new Promise((resolve, reject) => {
resolve();
throw 'Silenced Exception!';
});
p.catch(reason=>{
console.log('Will not be executed');
});
finally()
此方法在Promise
对象执行结束时调用,无论结果是完成或失败。在执行完then()
和catch()
后,都会执行finally()
。
Promise.prototype.finally(onFinally)
var p = new Promise(function(resolve, reject){
//...
});
p.finally(function(){
});
onFinally
为Promise
对象状态改变后执行的回调函数。由于无法知道Promise
对象的最终状态,所以finally
回调函数中不接收任何参数。
2、静态方法
语法:
Promise.resolve(thenable);
Promise.resolve(promise);
Promise.resolve(value);
此方法返回一个按给定值value
解析后的Promise
对象,如果value
带有then
方法(thenable
),则返回的Promise
对象会使用该value
的最终状态(resolved/rejected/pending/settled
);如果value
本身就是Promise
对象,则value
作为此方法的返回值;否则返回一个以value
为成功状态的的Promise
对象。
从一个普通值中解析:
let p = Promise.resolve(123);
p.then((value)=>{
console.log(value);//123
});
p = Promise.resolve('Success');
p.then((value)=>{
console.log(value);//Success
});
p = Promise.resolve([1, 2, 3]);
p.then(value=>{
console.log(value);//[1, 2, 3]
});
从一个Promise
对象中解析:
let original = Promise.resolve(66);
let p = Promise.resolve(original);
p.then((value)=>{
console.log(`value: ${value}`);
});
console.log(`original === p : ${original === p} `);
输出:
original === p : true
value: 66
从thenable
对象中解析:
let thenable = {
then: (onFulfill, onReject)=>{
onFulfill('fulfilled');
}
};
let p = Promise.resolve(thenable);
console.log(p instanceof Promise);//true
p.then(value=>{
console.log(value);//fulfilled
}, error=>{
//Will not be executed
});
如果在resolve
之前抛出错误,则Promise
对象被reject
,执行失败回调函数;相反,在resolve
之后抛出错误,Promise
对象被resolve
,执行成功回调函数。
let thenable = {
then: (onFulfill, onReject)=>{
throw new TypeError('Throwing');
resolve('resolving');
}
};
let p = Promise.resolve(thenable);
p.then(v=>{
//Will not be executed
}, e=>{
console.log(e);//TypeError: Throwing at Object.then (<anonymous>:3:9)
});
Promise.reject(reason);
此方法返回一个参数为失败原因(reason
)的Promise
对象(状态为rejected
)。
let p = Promise.reject('wrong');
//等价于
let p = new Promise((resolve, reject) => reject('wrong'));
p.then(function(result){
//Will not be executed
}, function(reason){
console.log(reason);//wrong
});
此方法的参数会原封不动的作为reject
的原因(reason):
let thenable = {
then(resolve, reject){
reject('wrong');
}
};
Promise.reject(thenable).catch(reason => {
console.log(reason === thenable);//true
});
Promise.reject(new Error('fail')).catch(reason => console.log(reason));
//Error: fail
// at <anonymous>:1:16
参数iterable
为一个可迭代对象,例如:Array
或String
。
此方法返回一个Promise
对象,该对象在iterable
参数内的所有Promise
对象都完成(resolved
)或者参数中不包含Promise
对象时执行完成回调函数;如果参数中Promise
对象有一个失败(rejected
),则此Promise
对象失败,执行失败时回调函数(不管其它Promise
对象是否完成);失败的原因为第一个失败的Promise
的原因。
let p1 = Promise.resolve(3);
let p2 = 1234;
let p3 = new Promise((resolve, reject) => {
setTimeout(resolve, 2000, 'Hello World!');
});
Promise.all([p1, p2, p3]).then(values => {
console.log(values);
});
如果iterable
为空,此方法同步返回一个已完成(resolved
)状态的Promise
对象;
let p = Promise.all([]);
console.log(p);//Promise {<resolved>: Array(0)}
如果iterable
中所有Promise
对象都变为完成状态或都iterable
中没有Promise
对象,则此方法异步的变为完成状态。
let arr = [Promise.resolve(true), Promise.resolve(2), Promise.resolve('a')];
let p = Promise.all(arr);
console.log(p);//Promise {<pending>}
setTimeout(()=>{
console.log(p);//Promise {<resolved>: Array(3)}
});
如果iterable
中有一个失败,则此方法会异步的将失败结果传给失败的Promise
对象的失败回调函数。
let reject = Promise.reject('abc').catch((reason)=>{
console.log(reason);//abc
});
let arr = [Promise.resolve(123), reject];
let p = Promise.all(arr);
console.log(p);//Promise {<pending>}
setTimeout(()=>{
console.log(p);//Promise {<resolved>: Array(2)}
});
let p1 = new Promise((resolve, reject)=>{
setTimeout(resolve, 1000, 'one');
});
let p2 = new Promise((resolve, reject)=>{
setTimeout(reject, 2000, 'two');
});
let p3 = new Promise((resolve, reject) => {
setTimeout(resolve, 3000, 'three');
});
let p = Promise.all([p1, p2, p3]).then(vlaues => {
console.log(values);
}, reason => {
console.log(reason);//two
});
console.log(p);//Promise {<pending>}
setTimeout(()=>{
console.log(p);//Promise {<resolved>: undefined}
}, 2500);
此方法返回一个Promise
对象,一旦iterable
中的某个Promise
对象被解决或者拒绝,则返回的Promise
对象就会被异步的解决或拒绝。如果iterable
是空的,则返回的Promise
对象永远是等待状态。如果iterable
中是一个或多个已解决或拒绝的Promise
对象,则返回值为第一个完成的Promise
对象。
let arr = [Promise.resolve(1), Promise.resolve('a')];
let p = Promise.race(arr);
console.log(p);//Promise {<pending>}
setTimeout(()=>{
console.log(p);//Promise {<resolved>: 1}
});
let p1 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, 'one');
});
let p2 = new Promise((resolve, reject) => {
setTimeout(resolve, 2000, 'two');
});
let p3 = new Promise((resolve, reject) => {
setTimeout(reject, 500, 'three');
});
Promise.race([p1, p2]).then((result)=>{
console.log(result);//one
}, (reason) => {
console.log(reason);
});
Promise.race([p1, p3]).catch((reason) => {
console.log(reason);//three
});