一、背景
Promise.prototype.finally是目前Stage 4的proposal,将纳入到ES 2018或ES 2019规范中。
promise被settled时有另种情况,或者fulfilled,或者rejected。
如果想要在上述不论哪种被settled的情况下,都做一件事,就不得不写成,
promise.then(f, f);
注意,Promise.prototype.then是可以接受两个函数作为参数的,
第一个函数,会在promise被fulfilled的时候执行,
第二个函数,如果提供了的话,会在promise被rejected的时候执行。
由于promise只能由fulfilled和rejected这两种状态被settled,
所以,这里两个函数,有且只有一个会被执行。
因此,本提案给Promise.prototype
添加了一个finally
方法,
以更好的表达上述场景的需要。
promise.finally(f);
二、promise.then
不幸的是,
promise.finally(f);
的执行结果,是与promise.then(f, f);
是不同的。
为了了解有哪些异同,这里有必要回顾一下promise.then(f, f);
的返回结果。
下文中“resolved”与“fulfilled”的异同,可以参考:Promise相关的几个术语。
可以简单的认为,fulfilled是promise的结果状态,
而resolved指的是new Promise((res, rej)=> ...);
中的res
函数被调用。
res
只能被调用一次,且它的参数可以是一个promise。
因此,一个resolved的promise,可能处于pending状态,也可能处于settled状态,
最终的settled结果,可能是fulfilled也可能是rejected。
// 1. 这是一个resolved为settled状态的promise
p=new Promise((res,rej)=>{
res(1);
res(2); // 第二次res调用,没有作用
});
// Promise {<resolved>: 1}
// 2. 这是一个resolved为pending状态的promise,最终fulfilled
p=new Promise((res,rej)=>res(new Promise((res,rej)=>setTimeout(res,1000))));
// Promise {<pending>}
p
// Promise {<resolved>: undefined}
// 3. 这是一个resolved为pending状态的promise,最终rejected
p=new Promise((res,rej)=>res(new Promise((res,rej)=>setTimeout(rej,1000))));
// Promise {<pending>}
p
// Promise {<rejected>: undefined}
以下对promise.then(f, f);
的返回结果,分情况进行分析:
(1)如果上述promise
被fulfilled了,则第一个f
被调用,
否则如果上述promise
被rejected了,则第二个f
被调用。
这两个f
,只会被调用一个,
因此,以下的例子,都用接受单个参数的then(f)
来说明问题。
(2)如果被调用的那个f
,返回了一个非promise的值,则then
会返回一个resolved为该值的promise。如果被调用的那个f
,抛了一个异常,则then
会返回了一个rejected为该异常的promise。
// 1. 返回一个非promise值
Promise.resolve(1).then(()=>2);
// Promise {<resolved>: 2}
// 2. 抛异常
Promise.resolve(1).then(()=>{ throw 2; });
// Promise {<rejected>: 2}
(3)如果被调用的那个f
,返回了一个resolved的promise,则then
会返回了一个新的具有相同resolved值的promise。如果被调用的那个f
,返回了一个rejected的promise,则then
会返回了一个新的,具有相同rejected值的promise。
// 1. 返回一个resolved的promise
// 该resolved的proimse,最终fulfilled
Promise.resolve(1).then(()=>new Promise((res,rej)=>res(2)));
// Promise {<resolved>: 2}
// 该resolved的promise,最终rejected
Promise.resolve(1).then(()=>new Promise((res,rej)=>res(Promise.reject(2))));
// Promise {<rejected>: 2}
// 2. 返回一个rejected的promise
Promise.resolve(1).then(()=>new Promise((res,rej)=>rej(3)));
// Promise {<rejected>: 3}
(4)如果被调用的那个f
,返回了一个pending的promise,
则then
也返回一个新的promise。
该promise的settled状态,取决于返回的那个pending promise的settled状态。
// 1. 返回一个pending的最终fulfilled的promise
p=Promise.resolve(1).then(()=>new Promise((res,rej)=>setTimeout(res,1000)));
// Promise {<pending>}
p
// Promise {<resolved>: undefined}
// 2. 返回一个pending的最终rejected的promise
p=Promise.resolve(1).then(()=>new Promise((res,rej)=>setTimeout(rej,1000)));
// Promise {<pending>}
p
// Promise {<rejected>: undefined}
三、promise.finally
下面我们来看一下promise.finally(f);
,
(1)f
是一个无参函数,不论该promise
最终是fulfilled还是rejected。
(2)finally
不改变promise
的状态,
// 1. fulfilled情形
// then返回了一个resolved为2的promise
Promise.resolve(1).then(()=>2,()=>3);
// Promise {<resolved>: 2}
// finally不改变原来resolved的状态
Promise.resolve(1).finally(()=>2);
// Promise {<resolved>: 1}
// 2. rejected情形
// then返回了一个resolved为3的promise
Promise.reject(1).then(()=>2,()=>3);
// Promise {<resolved>: 3}
// finally不改变原来reject的状态
Promise.reject(1).finally(()=>2);
// Promise {<rejected>: 1}
四、等价的async function写法
// 1. fulfilled情形
Promise.resolve(1).finally(alert);
// Promise {<resolved>: 1}
f = async ()=>{
try{
return 1;
}finally{
alert();
}
};
f();
// Promise {<resolved>: 1}
// 2. rejected情形
Promise.reject(1).finally(alert);
// Promise {<rejected>: 1}
f = async ()=>{
try{
throw 1;
}finally{
alert();
}
};
f();
// Promise {<rejected>: 1}