1. fulfilled酒请,rejected甫恩,pending
A Promise is an object that is used as a placeholder for the eventual results of a deferred (and possibly asynchronous) computation.
Any Promise object is in one of three mutually exclusive states: fulfilled, rejected, and pending:
A promise p is fulfilled if
p.then(f, r)
will immediately enqueue a Job to call the functionf
.
A promise p is rejected ifp.then(f, r)
will immediately enqueue a Job to call the function r.
A promise is pending if it is neither fulfilled nor rejected.
一個(gè)promise總共有三種狀態(tài),pending榛斯,fulfilled/rejected,new Promise
構(gòu)造函數(shù)創(chuàng)建的promise搂捧,初始處于pending狀態(tài)驮俗。
pending的時(shí)候不向Job Queue加入任何Job。
當(dāng)一個(gè)promise p
被fulfilled/rejected的時(shí)候异旧,會(huì)立即向名字為PromiseJobs
的Job Queue加入一個(gè)Job意述,這個(gè)Job做的事情就是調(diào)用p.then(f, r)
中的f
/r
。
2. settled吮蛹,resolved
A promise is said to be settled if it is not pending, i.e. if it is either fulfilled or rejected.
A promise is resolved if it is settled or if it has been “l(fā)ocked in” to match the state of another promise. Attempting to resolve or reject a resolved promise has no effect. A promise is unresolved if it is not resolved. An unresolved promise is always in the pending state. A resolved promise may be pending, fulfilled or rejected.
2.1 settled
一個(gè)promise被settled荤崇,指的是它脫離了pending狀態(tài),或者被fulfilled或者被rejected潮针。
2.2 resolved
resolve/reject一個(gè)promise术荤,
指的是調(diào)用new Promise((res,rej)=>{...})
中的res
/rej
函數(shù)。
調(diào)用了res
函數(shù)之后的promise每篷,稱(chēng)為resolved瓣戚。
2.3 如何理解“l(fā)ocked in”
A promise is resolved if it is settled or if it has been “l(fā)ocked in” to match the state of another promise.
要想理解“l(fā)ocked in”,首先要知道焦读,res
函數(shù)可以接受三種類(lèi)型的值作為參數(shù)子库,
或者是一個(gè)promise,或者是一個(gè)帶有then
方法的對(duì)象矗晃,或者是其他值仑嗅。
這里“l(fā)ocked in”指的是res
接受promise,或者接受帶有then
方法對(duì)象的情況,
這種方式進(jìn)行resolve仓技,會(huì)使得當(dāng)前的promise仍然處于pending狀態(tài)鸵贬,
其settled結(jié)果,與其參數(shù)對(duì)象的最終狀態(tài)有關(guān)脖捻。
例子:
(1)res
的參數(shù)為promise的例子阔逼,
a = new Promise((res,rej)=>setTimeout(()=>res(1),1000));
b = new Promise((res,rej)=>res(a));
b.then(v=>console.log(v));
(2)res
的參數(shù)為帶then
方法的對(duì)象的例子,
a = {
then:(res,rej)=>setTimeout(()=>res(1),1000)
};
b = new Promise((res,rej)=>res(a));
b.then(v=>console.log(v));
2.4 多次resolve無(wú)效
Attempting to resolve or reject a resolved promise has no effect.
一個(gè)promise一旦resolved地沮,再次resolve/reject將失效嗜浮。
無(wú)論第一次resolve所使用的參數(shù)是什么,
例如诉濒,即使第一調(diào)用res
仍然使promise處于pending狀態(tài)周伦。
a = new Promise((res,rej)=>{
res({
then:(res,rej)=>setTimeout(()=>res(1),1000)
});
res(2);
setTimeout(()=>rej(3),1000);
});
a.then(
v => console.log(v),
e => console.warn(e)
);
3. Enqueue Job
3.1 何時(shí)p.then(f, r)會(huì)Enqueue Job
如果promise p
還沒(méi)有被settled,那么p.then(f, r)
未荒,會(huì)將f
/r
放入promise的[[PromiseFulfillReactions]]
/[[PromiseRejectReactions]]
列表尾部专挪。
如果p
已經(jīng)被settled,會(huì)向名為PromiseJobs
的Job Queue中添加一個(gè)用來(lái)處理fulfilled/rejected的PromiseReactionJob片排。
因此寨腔,一個(gè)已經(jīng)settled的promise,每次調(diào)用p.then(f, r)
會(huì)Enqueue Job率寡。
[[PromiseFulfillReactions]]
和[[PromiseRejectReactions]]
的作用是迫卢,當(dāng)promise處于pending狀態(tài)時(shí),保存p.then(f, r)
所添加的處理器函數(shù)f
和r
冶共。
3.2 使用res / rej Enqueue的兩種Job
res
會(huì)出現(xiàn)在以下兩個(gè)地方:
(1)帶有then
方法的對(duì)象中乾蛤,{then:(res,rej)=>{...}}
用一個(gè)帶有then
方法的對(duì)象調(diào)用res
,會(huì)向名為PromiseJobs
的Job Queue中添加一個(gè)PromiseResolveThenableJob捅僵。
(2)new Promise((res,rej)=>{...})
構(gòu)造函數(shù)中
調(diào)用res
/rej
家卖,會(huì)導(dǎo)致promise被settled,(只能被settle一次)
此時(shí)會(huì)清空promise的[[PromiseFulfillReactions]]
和[[PromiseRejectReactions]]
列表庙楚,并向名為PromiseJobs
的Job Queue中添加一個(gè)用來(lái)處理fulfilled/rejected的 PromiseReactionJob上荡。
因此,調(diào)用res
/rej
總是會(huì)Enqueue Job馒闷。
當(dāng)promise被settled的時(shí)候酪捡,[[PromiseFulfillReactions]]
和[[PromiseRejectReactions]]
就沒(méi)有用了,因?yàn)閟ettled狀態(tài)的promise纳账,即使再添加處理器p.then(f, r)
逛薇,也是直接Enqueue Job,和[[PromiseFulfillReactions]]
和[[PromiseRejectReactions]]
無(wú)關(guān)疏虫。
a = new Promise(res=>setTimeout(()=>res(1),1000));
a.then(v=>console.log(v));
setTimeout(()=>a.then(v=>console.warn(v)),2000);
參考
StackOverflow: What is the correct terminology for javascript promises
ECMAScript 2018 Language Specification