<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                >[info]原文地址 http://www.hmoore.net/cris/es6/504477 目錄 (づ ̄ 3 ̄)づ=> [TOC] ## 序 本文會對Promise規范進行一個比較完整的實現,目的是為了加深對Promise各個特性的理解從而更好的應用。 >[warning] **注意**:本文依據[Promises/A+](https://promisesaplus.com)規范進行Promise的實現 ## 1.Promise/A+ 術語 ### 1.1. promise > promise是一個對象或則函數,它的表現是依據[Promises/A+](https://promisesaplus.com)這篇規范說明來定義的。 1.1. `promise` is an object or function with a then method whose behavior conforms to this specification. ### 1.2. theable > thenable是一個定義了then方法的對象或則函數。 `thenable` is an object or function that defines a then method. ### 1.3. value >value可以是任何合法的JS值,甚至包括undefined、一個thenable、一個promise。 `value` is any legal JavaScript value (including undefined, a thenable, or a promise). ### 1.4. exception > exception是一個用throw語句拋出的值。 `exception` is a value that is thrown using the throw statement. ### 1.5. reason > reason是一個為什么promise會被拒絕的理由。 `reason` is a value that indicates why a promise was rejected. ## Promise規范要求 >[info] 判斷一個東東是不是Promise,有三項主要的特征可作為參考 - Promise有三種狀態 `pending` 、`fulfilled`、`rejected` - Promise含有then方法 - Promise含有`Promise Resolution Procedure` (promise的狀態轉換處理方法)。 ### 2.1. Promise狀態 >[success] 一個promise必須處于 pending 、fulfilled、rejected 三種狀態中的其中一種 下面是一個promise最基本的使用demo,我們先有個印象。 - 其中promise實例化的時候傳入了一個函數作為參數,這個函數我們稱之為 `executor` ,它能告訴我們何時將promise狀態從pending轉化為其余兩態中的一態。 - 而 `then` 方法是實例化對象下的一個方法,它能傳入兩個參數,**一般**是兩個回調函數,對應fulfilled和rejected兩個狀態,當promise從pengding狀態轉化成其中一個狀態時就會觸發對應的回調函數。 ``` let p = new Promise((resolve,reject)=>{ let x = Math.random(); console.log(x); if (x > .5) { resolve('我是你許下的諾言的那個東東'); } else { reject('我是你未能實現諾言的理由'); } }); p.then((value)=>{ //綁定成功時的回調函數 console.log('fulfilled:',value); //fulfilled:我是你許下的諾言的那個東東 },(reason)=>{ //綁定失敗時的回調函數 console.log('rejected:',reason); //rejected:我是你未能實現諾言的理由 }); ``` #### 2.1.1. pending狀態 > 當Promise處于pending狀態時,它可能轉換為fulfilled或則rejected狀態。 When pending, a promise:may transition to either the fulfilled or rejected state. #### 2.1.2. fulfilled狀態 > 當Promise處于fulfilled狀態時,它不再能轉換為其它狀態 且 它必須有一個值,這個值不能被更改。 When fulfilled, a promise: - must not transition to any other state. - must have a value, which must not change. #### 2.1.3 rejected狀態 > 當promise處于rejected時,它不再能轉換為其它狀態 且 它必須有一個理由,這個理由不能被更改。 When rejected, a promise: - must not transition to any other state. - must have a reason, which must not change. >[danger]**注意**: 當promise處于fulfilled或則rejected時,它都有一個值,這個值不能被更改,但是可以像使用常量一樣在這個值下面掛載其它值。 Here, “must not change” means immutable identity (i.e. ===), but does not imply deep immutability. ### 2.1. Promise實現 **請先回顧一下我們在說Promise狀態時候最初的那個demo** 我們通過實例化Promise時傳入了一個參數,這個參數是一個執行函數(executor),它能決定什么時候將Promise轉換成fulfilled什么時候轉換成rejected。 ``` const PENDING = 'pending'; const FULFILLED = 'fulfilled'; const REJECTED = 'rejected'; function Promise(executor){ let self = this; //緩存下 self.value = undefined; //用來存放value和reason,因為promise只會處于一種狀態故可只用一個變量來表示。 self.status = PENDING; //將初始狀態設置為pending self.onFulfilledCallbacks = []; //用來存放所有成功的回調函數 self.onRejectedCallbacks = []; //用來存放所有失敗的回調函數 try{ executor(resolve,reject); //調用執行函數,將resolve和reject方法作為參數傳入 }catch (e){ reject(e); //若執行函數中存在異常直接用拋出的值來拒絕promise } //----------------------------------------------------------------------------------------------------------- function resolve(value){ //此方法會隨著executor傳入而傳入 setTimeout(function(){ if(self.status === PENDING){ //確保狀態只會改變一次 self.status = FULFILLED; //改變狀態 self.value = value; //賦予一個值 self.onFulfilledCallbacks.forEach(cb => cb(self.value)); //2.2.2. //2.2.6. } }) } function reject(reason){ setTimeout(function(){ if(self.status === PENDING){ self.status = REJECTED; self.value = reason; self.onRejectedCallbacks.forEach(cb => cb(self.value)); } }) } } ``` 以上實現了2.1. ,promise的三種狀態以及狀態之間的改變。 >[info]#### executor,形參、實參、作用域鏈 我們可以發現最終轉換狀態時通過Promise內部的兩個方法resolve和reject,這個兩個方法是在什么時候傳入的呢? **一個函數的參數查找,是從調用這個函數時所處的作用域開始查找的。** new Promise傳入的executor,是參數也是對executor函數的定義,此時executor的resolve和reject為**形參**。 我們new Promise的時候,會執行構造函數Promise內的代碼,也就是在這時executor被執行,而executor此時所處的作用域是在Promise構造函數內部,resolve和reject方法作為**實參**被傳入。 ### 2.2. then方法 >[success] 一個promise必須提供一個then方法來使用它將要或則說已經被賦予的 value 或則 reason,一個promise的then方法接收兩個參數 ``` promise.then(onFulfilled,onRejected) ``` #### 2.2.1. then參數 > then中的參數皆為可選參數,如果onFulfilled或則說onRejected不是一個函數,那么將會被忽略。 Both onFulfilled and onRejected are optional arguments: - If onFulfilled is not a function, it must be ignored. - If onRejected is not a function, it must be ignored. #### 2.2.2. 如果onFulfilled是一個函數 - 如果onFulfilled是一個函數,它必須在promise狀態轉換為fulfilled時候就被調用,并且promise被賦予的value會成為這個函數(onFulfilled)的第一個參數。 - onFulfilled不能在promise狀態轉化為fulfilled前就調用 - onFulfilled函數不能重復調用 原文規范詳見[Promises/A+](https://promisesaplus.com) #### 2.2.3. 如果onRejected是一個函數 - 如果onRejected是一個函數,它必須在promise狀態轉換為rejected時候就被調用,并且promise被賦予的reason會成為這個函數(onRejected)的第一個參數。 - onRejected不能在promise狀態轉化為rejected前就調用 - onRejected函數不能重復調用 #### 2.2.4. onFulfilled 或則 onRejected 必須在執行棧 只存在 `platform code` 時才能被調用。 #### 2.2.5. onFulfilled 和 onRejected 必須被當做函數調用。 #### 2.2.6. 同一個promise實例可以調用多次then - 當一個promise轉化為fulfilled狀態,所有onFulfilled callback會按照回調函數通過then添加時的順序而執行。 - 當一個promise轉化為rejected狀態,所有onRejected callback會按照回調函數通過then添加時的順序而執行。 **釋**:then在同一個promise實例下多次調用,意味著可以在同一個promise的同一種狀態下綁定多個不同的回調函數,而這些回調函數執行的順序和它們被綁定時的順序相同。 #### 2.2.7. then必會返回一個新的promise ``` promise2 = promise1.then(onFulfilled,onRejected); ``` - 如果onFulfilled或onRejected回調函數中返回了一個值,假定為x,那么調用一個 promise解析方法 `[[Resolve]](promise2,x)`。 - 如果onFulfilled或者onRejected拋出了一個 `exception`(異常) `e` , `promise2` 必須以這個e作為reason來拒絕promise,使其狀態改變為rejected。 - 如果onFulfilled不是一個函數且 `promise1` 的狀態為fulfilled,`promise2`必須以 `promise1` 的值來fulfilled。 - 如果onRejected不是一個函數且 `promise1` 的狀態為rejected,`promise2`必須以 `promise1` 的理由來rejected。 ### 2.2. Promise實現 2.2.提的是一個then的實現規則,而then主要作用為promise綁定回調函數,當promise轉換狀態時會自動調用對應的回調函數。(對應規范2.2.2-2.2.3) **其實就是發布訂閱模式啦** ``` function Promise(){ ... function resolve(value){ setTimeout(function(){ //2.2.4. if(self.status === PENDING){ //2.2.2.3-2.2.2.4 self.status = FULFILLED; self.value = value; self.onFulfilledCallbacks.forEach(cb => cb(self.value)); //2.2.6. } }) } function reject(reason){ setTimeout(function(){ if(self.status === PENDING){ //2.2.3.3-2.2.3.4 self.status = REJECTED; self.value = reason; self.onRejectedCallbacks.forEach(cb => cb(self.value)); } }) } } //--------------------------------------------------------------------------------------------------- Promise.prototype.then = function (onFulfilled, onRejected) { //2.2.1. //2.2.7.3-2.2.7.4 //2.2.5. onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value; onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason}; let self = this, promise2; //2.2.7.0 //聲明要返回的promise2 if(self.status === PENDING){ //2.2.7. return promise2 = new Promise(function(resolve,reject){ //存儲then方法綁定的回調函數 //2.2.6. self.onFulfilledCallbacks.push((value)=>{ try{ let x = onFulfilled(value); resolvePromise(promise2,x,resolve,reject); //2.2.7.1 }catch (e){ reject(e); //2.2.7.2 } }); self.onRejectedCallbacks.push((reason)=>{ try{ let x= onRejected(reason); resolvePromise(promise2,x,resolve,reject); }catch (e){ reject(e); } }); }); } }; ``` #### 關于platform code Here “platform code” means engine, environment, and promise implementation code. In practice, this requirement ensures that onFulfilled and onRejected execute asynchronously, after the event loop turn in which then is called, and with a fresh stack. This can be implemented with either a “macro-task” mechanism such as setTimeout or setImmediate, or with a “micro-task” mechanism such as MutationObserver or process.nextTick. Since the promise implementation is considered platform code, it may itself contain a task-scheduling queue or “trampoline” in which the handlers are called. 上面一大段話的意思大致上就是要求 `onFulfilled` 和 `onRejected` 回調函數確保異步執行。我們可以選擇用宏任務(setTimeout/setImmediate)或則微任務(process.nextTix/MutationObserver)來完成這項規范。 **這里我們通過在Promise中的resolve和reject方法中套了一個setTimeout()來實現。** ``` function resolve(value){ setTimeout(function(){ //2.2.4. if(self.status === PENDING){ //2.2.2.3-2.2.2.4 self.status = FULFILLED; self.value = value; self.onFulfilledCallbacks.forEach(cb => cb(self.value)); //2.2.6. } }) } ``` 這樣setTimeout中的代碼就會在下一個新的執行棧中執行。**即使executor中的代碼是同步代碼也一樣**。 ``` let p = new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve('resolve'); }) }); p.then((value)=>{ console.log('fulfilled:',value); },(reason)=>{ console.log('rejected:',reason); }); console.log('----------------'); //輸出 >>>---------------- >>>fulfilled: resolve //---------------------------------------------------------------------------------- let p = new Promise((resolve,reject)=>{ resolve('resolve'); }); p.then((value)=>{ console.log('fulfilled:',value); },(reason)=>{ console.log('rejected:',reason); }); console.log('----------------'); //輸出 >>>---------------- >>>fulfilled: resolve ``` #### 情景:值的穿透 下面的例子中本應是第一個then中的參數會穿透到第二then中作為參數。 **下面兩句再集合resolvePromise方法即是穿透原因** ``` Promise.prototype.then = function (onFulfilled, onRejected) { //2.2.1. //2.2.7.3-2.2.7.4 //2.2.5. onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value; //結合resolvePromise方法即是穿透原因 onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason}; //繼續把異常往后拋 ... //------------------------------------------------- let p = new Promise((resolve,reject)=>{ resolve('resolve'); }); p.then().then((value)=>{ console.log(value); //會輸出resolve }); ``` ### 2.3. Promise狀態解析方法(promise resolution procedure) ``` let x= onRejected(reason); resolvePromise(promise2,x,resolve,reject); //resolve/reject為promise2的resolve/reject ``` Promise狀態解析方法的作用是將then時返回的promise2的狀態改變并賦予其vlaue/reason。 - 如果 `x` 是一個thenable,那么該方法將試圖將以 `x` 的狀態來改變 `promise2` 的狀態 - 否則就將 `promise2` 改成 `fulfilled` 狀態,并且value即為 `x` 的值 #### 2.3.1. 如果 `promise2` 和 `x` 是引用關系,則拋出一個 `TypeError` 做為理由來 `reject ` promise2。 #### 2.3.2. 如果 `x` 是一個promise ,讓promise2采用它的狀態。 - 如果 `x` 處于pending,promise2 必須保持pending直到 x 轉換為 fulfilled或則rejected。 - 如果 `x` 是 `fulfilled`狀態,讓promise2也為fulfilled,并且讓promise2的value為x的value。 - 如果 `x` 是 `rejected`狀態,讓promise2也為rejected,并且讓promise2的value為x的reason。 #### 2.3.3. 如果 `x` 是一個對象或則函數 - Let `then` be `x.then` - 如果檢索 `x.then` 時候拋出了一個異常`e`,那么以這個 `e`來 `rejecte` promise2。 - 如果 `then` 是一個函數,用`x`作為`this`,`resolvePromise`作為第一個參數,`rejectPromise`作為第二個參數來 `call`它。 - 如果`resolvePromise`被調用,**循環調用** `promise狀態解析方法`(原本的x替換為調用resolvePromise傳入的參數,假定為y)。 - 如果`rejectPromise`被調用,則reject Promise2,reason為調用rejectPromise傳入的參數 - 如果`resolvePromise` 和 `rejectPromise` 同時被調用或則多次調用,那么第一個調用的擁有優先權,其它的會被忽略。 - 如果調用 `then` 的時候拋出了一個異常 `e` - 如果 `resolvePromise` 或 `rejectPromise` 已經被調用,則忽略它。 - 否則,則用這個`e`來 `reject` promise2。 - 如果then不是一個函數,則用`x`來`fulfilled `promise2 #### 2.3.4. 如果 `x` 不是一個函數也不是一個對象,則用`x`來`fulfilled `promise2 ### 2.3.3. Promise實現 resolvePromise方法針對的是then綁定的回調函數中的return值進行解析,一般情況是: - 當return的是普通類型的值,那么會以這個值來fulfilled promise2 - 如果是一個promise,那么會以這個x promise的結果來fulfilled/rejected promise2 ``` function resolve(value) { if(value instanceof Promise){ //和resolvePromise有點聯系的是 當then return的promise中又resolve了一個promise會先走這,會將resolve里的promise的值賦給調用resolve的promise(說法欠妥,意會即可) return value.then(resolve,reject); //這意味著如果promise1 resolve中是一個promise2,那么promise1狀態的改變時間會被推遲,直到promise2狀態改變調用promise2的回調時,promise1狀態才會改變才會觸發promise1的回調 } ... //--------------------------------------------------------------------------------------------------------- function resolvePromise(promise2,x,resolve,reject){ if(x === promise2){ //2.3.1. return reject(new TypeError('禁止循環引用!')); } let called =false; //2.3.2. if(x instanceof Promise){ if(x.status === PENDING){ //2.3.2.1 x.then((y)=>{ resolvePromise(promise2,y,resolve,reject); //因為此時的y,有可能也是一個promise //掛上一個鉤子只要x狀態轉化為成功態就遞歸調用resolvePromise },reject); }else{ //此分支存在的意義在于若executor調用resolve/reject不是異步的且不在resolve/reject中設置setTimeout,意味著當new的時候就會返回一個帶狀態的promise就會走這里。 x.then(resolve,reject); //2.3.2.2-2.3.2.3 //只要x狀態改變,就以x的狀態和值來改變promise2的狀態和值 //這個值可能是一個promise,前提是在上面那種假設實現中 //如果不符合上面那種實現且不想像規范一樣允許值可以為一個promise或則對象 可除去此分支 } }else if(x!=null&&((typeof x === 'function')||(typeof x === 'object'))){ //2.3.3. try{ let then = x.then; //2.3.3.1 if(typeof then === 'function'){ //2.3.3.3. then.call(x,(y)=>{ if(called) return; //2.3.3.3.3. called = true; resolvePromise(promise2,y,resolve,reject); //在resolve中又包含promise的情況下,由于resolve中的 value.then存在,當前回調調用時,resolve中的promise狀態一定已經改變,在狀態已經改變的時候利用then綁定回調,會走then中的status==fulfilled或則rejected分支 },(reason)=>{ if(called) return; called = true; reject(reason); }); }else{ resolve(x); //2.3.3.4. //1.3 } }catch (e){ if(called) return; //2.3.3.3.4.1. called = true; reject(e); //2.3.3.2. //2.3.3.3.4.2. } }else{ //2.3.4. resolve(x); } } ``` #### 情景:當return的是promise且該promise的resolve/reject ()中 也是一個promise ``` let p = new Promise((resolve,reject)=>{ resolve('resolve1'); }); p.then((value)=>{ return new Promise((resolve,reject)=>{ resolve(new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve('別慫') }); })); }); }).then((value)=>{ console.log(value); //別慫 }); console.log('----------------'); ``` 可見最終的value值為最里層的value值,這樣的實現關鍵在于遞歸調用resolvePromise。 ``` ... function resolve(value) { if(value instanceof Promise){ return value.then(resolve,reject); ... if(x instanceof Promise){ if(x.status === PENDING){ //2.3.2.1 x.then((y)=>{ resolvePromise(promise2,y,resolve,reject); },reject); }else{ x.then(resolve,reject); } } ``` 以上這段代碼,當promise1執行回調的時候,會將x傳入resolvePromise執行,此時由于resolve()方法中的setTimeout,該x是pending狀態進pending分支,該分支會為X掛上一個鉤子,當它狀態轉換后會再次調用resolvePromise。 - 如果x的resolve中傳入的也是一個promise (y),由于resolve中添加的value.then,它會推遲x的狀態轉換,這意味著X狀態轉換時,y的狀態一定已經轉換,于是會走下面那個分支,調用y.then,**而因為y的狀態已經轉換,在then方法中此時就不再能通過狀態改變時觸發回調函數**,故要支持此功能需要在then中添加`self.status===FULFILLED/REJECTED`分支。 ``` }else if(self.status === FULFILLED){ return promise2 = new Promise(function(resolve,reject){ setTimeout(function(){ try{ let x =onFulfilled(self.value); resolvePromise(promise2,x,resolve,reject); }catch(e){ reject(e); } }) }); }else{ return promise2 = new Promise(function(resolve,reject){ setTimeout(function(){ try{ let x =onRejected(self.value); resolvePromise(promise2,x,resolve,reject); }catch(e){ reject(e); } }) }); } ``` 這里用了setTimeout是為了確保回調函數會異步執行。(針對2.2.4.) - 如果x的resolve傳入的只是一個普通的值。。。呵呵噠,那就直接resolve(x)咯 >[warning] **值得注意的是**: 如果沒有在 `resolve()` 方法中對value進行判斷,那么此時嵌套promise中再嵌套一層promise輸出結果會是一個promise。因為第二個promise不會等第三個promise狀態轉換后才轉換狀態,這意味著第二個promise的值就為第三個promise對象。 #### 情景:當new的promise中的resolve也是一個promise,而這個promise的resolve中又是一個promise... 此時情況同上個情景,得益于`then()`中對value的判斷,它會推遲父promise狀態的轉變。 如果沒有這個判斷和推遲,那么也可能最終得到的value是個promise對象。(這是規范允許的,但NodeJS和blubird對promise規范的實現都對父promise的狀態轉換進行了推遲) #### 情景:在一個已經轉換了狀態的promise中再次調用這個promise的then方法 此時也會走then中的self.status === FULFILLED/REJECTED 的分支,再次證明需要在then中添加這兩個分支并用上settimeout ``` p1.then((value)=>{ //執行此回調時p1狀態已經改變 p1.then(...); }); ``` #### x instanceof Promise 和 typeof x=function... 遞歸的區別 instance分支下的遞歸 因為存在對promise狀態的判斷,當`resolve()`沒有對value進行判斷時,instance分支下的結果value最終可能為promise對象,而x.then分支下因為沒有對promise狀態進行判斷,故不會出現value為promise對象的情況。 ## 其余Promise方法的實現 ### Promise.prototype.catch 此方法實現灰常簡單,只需在最后一個then綁定完回調后再綁定一個錯誤的回調即可 ``` promise.prototype.catch = function(onRejected){ this.then(null,onRejected); } ``` ### Promise.all 此方法傳入一組promise實例再返回一個最終的promise實例,當所有promise都轉為fulfilled時返回的最終的promise實例將會轉換為fulfilled,此時這個promise的值為傳入的promise的值的集合。而如果傳入的那組promise中有一個rejected,返回的promise就會rejected。 ``` Promise.all = function(promises){ return new Promise((resolve,reject)=>{ let result = [], count = 0; function done(i,data){ result[i] = data; if(++count===promises.length){ resolve(result); } } for(let i=0;i<promises.length;++i){ promises[i].then((value)=>{ done(i,value); },(reason)=>{ reject(reason); }); } }); } ``` ### Promise.race 也是傳入一組promise返回一個promise,哪個promise先轉換狀態,就返回這個promise的結果 ``` Promise.race = function(promises){ return new Promise((resolve,reject)=>{ for(let i=0;i<promises.length;++){ promises[i].then(resolve,reject); } }); } ``` ### Promise.promisify 將一個異步函數promise化,使其可以then,可以鏈式書寫 ``` Promise.promisify = function(fn){ return function(...args){ return new Promise((resolve,reject)=>{ fn.apply(null,[...args,function(err,data){ err?reject(err):resolve(data); }]); }); } } ``` ### Promise.promisifyAll 將一個對象下的所有方法都promisify化 ``` Promise.promisifyAll = function(obj){ for(var attr in obj){ if(obj.hasOwnProperty(key)&&typeof obj[attr]==='function'){ obj[attr+'Async'] = Promise.promisify(obj[attr]); } } } ``` ## 測試 要對實現的Promise進行測試,除了實現t規范要求then方法和catch方法外還需要先在你的promise下添加一個方法 ``` Promise.deferred = Promise.defer = function(){ let defer = {}; defer.promise = new Promise(function(resolve,reject){ defer.resolve = resolve; defer.reject = reject; }); return defer; } ``` 然后按下述進行測試 ``` npm i -g promises-aplus-tests promises-aplus-tests yourFileName.js ``` ## 實現代碼【終板】 ``` const PENDING = 'pending'; const FULFILLED = 'fulfilled'; const REJECTED = 'rejected'; function Promise(executor) { let self = this; //緩存下 self.value = undefined; //用來存放value和reason,因為promise只會處于一種狀態故可只用一個變量來表示。 self.status = PENDING; //將初始狀態設置為pending self.onFulfilledCallbacks = []; //用來存放所有成功的回調函數 self.onRejectedCallbacks = []; //用來存放所有失敗的回調函數 try { executor(resolve, reject); //調用執行函數,將resolve和reject方法作為參數傳入 } catch (e) { reject(e); //若執行函數中存在異常直接用拋出的值來拒絕promise } function resolve(value) { if (value instanceof Promise) { //和resolvePromise有點聯系的是 當then return的promise中又resolve了一個promise會先走這,會將resolve里的promise的值賦給調用resolve的promise(說法欠妥,意會即可) return value.then(resolve, reject); //這意味著如果promise1 resolve中是一個promise2,那么promise1狀態的改變時間會被推遲,直到promise2狀態改變調用promise2的回調時,promise1狀態才會改變才會觸發promise1的回調 } setTimeout(function () { if (self.status === PENDING) { self.status = FULFILLED; self.value = value; self.onFulfilledCallbacks.forEach(cb => cb(self.value)); //2.2.2. //2.2.6. } }) } function reject(reason) { setTimeout(function () { if (self.status === PENDING) { self.status = REJECTED; self.value = reason; self.onRejectedCallbacks.forEach(cb => cb(self.value)); //2.2.3. //2.2.6. } }) } } Promise.prototype.then = function (onFulfilled, onRejected) { //2.2.1. //2.2.7.3-2.2.7.4 //2.2.5. onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value; onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }; let self = this, promise2; //2.2.7.0 //聲明要返回的promise2 if (self.status === PENDING) { //2.2.7. return promise2 = new Promise(function (resolve, reject) { //存儲then方法綁定的回調函數 //2.2.6. self.onFulfilledCallbacks.push((value) => { try { let x = onFulfilled(value); resolvePromise(promise2, x, resolve, reject); //2.2.7.1 //resolve/reject屬于promise2 //若此方法執行說明promise1狀態已經更改 } catch (e) { reject(e); //2.2.7.2 } }); self.onRejectedCallbacks.push((reason) => { try { let x = onRejected(reason); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }); }); } else if (self.status === FULFILLED) { return promise2 = new Promise(function (resolve, reject) { setTimeout(function () { try { let x = onFulfilled(self.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }) }); } else { return promise2 = new Promise(function (resolve, reject) { setTimeout(function () { try { let x = onRejected(self.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }) }); } }; function resolvePromise(promise2, x, resolve, reject) { if (x === promise2) { //2.3.1. return reject(new TypeError('禁止循環引用!')); } let called = false; //2.3.2. if (x instanceof Promise) { if (x.status === PENDING) { //2.3.2.1 x.then((y) => { resolvePromise(promise2, y, resolve, reject); //因為此時的y,有可能也是一個promise //掛上一個鉤子只要x狀態轉化為成功態就遞歸調用resolvePromise }, reject); } else { //此分支存在的意義在于若executor調用resolve/reject不是異步的且不在resolve/reject中設置setTimeout,意味著當new的時候就會返回一個帶狀態的promise就會走這里。 x.then(resolve, reject); //2.3.2.2-2.3.2.3 //只要x狀態改變,就以x的狀態和值來改變promise2的狀態和值 //這個值可能是一個promise,前提是在上面那種假設實現中 //如果不符合上面那種實現且不想像規范一樣允許值可以為一個promise或則對象 可除去此分支 } } else if (x != null && ((typeof x === 'function') || (typeof x === 'object'))) { //2.3.3. try { let then = x.then; //2.3.3.1 if (typeof then === 'function') { //2.3.3.3. then.call(x, (y) => { if (called) return; //2.3.3.3.3. called = true; resolvePromise(promise2, y, resolve, reject); //在resolve中又包含promise的情況下,由于resolve中的 value.then存在,當前回調調用時,resolve中的promise狀態一定已經改變,在狀態已經改變的時候利用then綁定回調,會走then中的status==fulfilled或則rejected分支 }, (reason) => { if (called) return; called = true; reject(reason); }); } else { resolve(x); //2.3.3.4. //1.3 } } catch (e) { if (called) return; //2.3.3.3.4.1. called = true; reject(e); //2.3.3.2. //2.3.3.3.4.2. } } else { //2.3.4. resolve(x); } } Promise.deferred = Promise.defer = function () { let defer = {}; defer.promise = new Promise(function (resolve, reject) { defer.resolve = resolve; defer.reject = reject; }); return defer; }; Promise.prototype.catch = function (onRejected) { this.then(null, onRejected) }; Promise.resolve = function (value) { return new Promise((resolve, reject) => { resolve(value); }) }; Promise.reject = function (reason) { return new Promise((resolve, reject) => { reject(reason); }) }; Promise.all = function(promises){ return new Promise((resolve,reject)=>{ let result = []; let count = 0; function done(i,data){ result[i] = data; if(++count === promises.length){ resolve(result); } } for(let i=0;i<promises.length;++i){ promises[i].then((value)=>{ done(i,value); },reject); } }) }; Promise.race = function(promises){ return new Promise(function(resolve,reject){ for(let i=0;i<promises.length;++i){ promises[i].then(resolve,reject); } }); }; Promise.promisify = function(fn){ return function(...args){ return new Promise((resolve,reject)=>{ fn.apply(null,[...args,function(err,data){ err?reject(err):resolve(data); }]); }); } }; Promise.promisifyALL = function(obj){ for(var key in obj){ if(obj.hasOwnProperty(key)&&typeof obj[key]=='function'){ obj[key+'Async'] = Promise.promisify(obj[key]); } } }; module.exports = Promise; ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看