成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

promise/A+規(guī)范翻譯以及手寫實現

LiuZh / 698人閱讀

摘要:如果實現滿足所有要求,則實現可能允許。本條款允許使用特定于實現的方法來采用已知一致承諾的狀態(tài)。接下來根據規(guī)范進行手寫實現注釋偷懶就將對應的規(guī)范標注出來,其實基本上就是對著規(guī)范實現。

如果要手寫實現promise,那么先看看promise/A+規(guī)范,再來實現,將會事半功倍。
那么我先翻譯一下Promise/A+規(guī)范中的內容。

術語
1.1 promise 是一個帶有符合此規(guī)范的then方法的對象或者函數。
1.2 thenable 是一個定義了一個then方法的對象或者函數。
1.3 value 是一個任意合法的JavaScript值(包括undefined, thenable,或者promise)。
1.4 exception 是一個使用throw語句拋出的值。
1.5 reason 是一個指出為什么promise被rejected的值。

要求
2.1 promise 狀態(tài)

一個promise必須是三種狀態(tài)其中的一種狀態(tài):pending,fulfilled 或者 rejected。

2.1.1 當promise處于pending狀態(tài)時:

   2.1.1.1 可以轉變到 fulfilled 或者 rejected 狀態(tài)。

2.1.2 當promise處于fulfilled狀態(tài)時:

   2.1.2.1 一定不能夠轉變到其他任何一種狀態(tài)。
   2.1.2.2 必須有一個value,并且這個值一定不能改變。

2.1.3 當promise處于rejected狀態(tài)時:

   2.1.3.1 一定不能夠轉變到其他任何一種狀態(tài)。
   2.1.3.2 必須有一個reason,并且這個值不能夠改變。
   

在這里,“一定不能改變”意味著不可變的身份(即===),但并不意味著深層不變性。(個人理解為是value/reason指向的地址是不可變的,但假若value/reason為一個對象,則對象內的值是可變的。)

2.2 then 方法
一個promise必須提供一個then方法去訪問當前或者最終的value或者reason。
一個promise的then方法接受兩個參數:

promise.then(onFulfilled, onRejected)

2.2.1 onFulfilled 和 onRejected 都是可選的參數:

    2.2.1.1 如果 onFulfilled  不是一個函數,它必須被忽略。
    2.2.1.2 如果 onRejected 不是一個函數,它必須被忽略。

2.2.2 如果 onFulfilled 是一個函數:

   2.2.2.1 promise 是 fulfilled 狀態(tài)時它必須被調用,并且 promise 的 value 作為它的第一個參數。
   2.2.2.2 它一定不能在 promise 進入 fulfilled 狀態(tài)之前被調用。
   2.2.2.3 它一定不能夠調用超過一次。

2.2.3 如果 onRejected 時一個函數:

   2.2.3.1 promise 是 rejected 狀態(tài)時它必須被調用,并且 promise 的 reason 作為它的第一個參數。
   2.2.3.2 它一定不能在 promise 進入 rejected 狀態(tài)之前被調用。
   2.2.3.3 它一定不能夠調用超過一次。

2.2.4 直到執(zhí)行上下文堆棧僅包含平臺代碼之前,onFulfilled 或 onRejected 不能夠被調用。[3.1]
2.2.5 onFulfilled 和 onRejected 必須以函數的形式被調用(即沒有this值)。[3.2]
2.2.6 then 可以在同一個promise被調用多次:

   2.2.6.1 當 promise 處于 fulfilled 狀態(tài)時,各個 onFulfilled 回調必須按其原始調用的順序執(zhí)行。
   2.2.6.2 當 promise 處于 rejected 狀態(tài)時,各個 onRejected 回調必須按其原始調用的順序執(zhí)行。

2.2.7 then 必須返回一個promise [3.3]:

 promise2 = promise1.then(onFulfilled, onRejected);
   2.2.7.1 如果 onFulfilled 或 onRejected 返回一個值 x,運行Promise解決程序 [[Resolve]](promise2, x)。
   2.2.7.2 如果 onFulfilled 或 onRejected 拋出一個意外 e,promise2 必須以 e 為 reason 被 rejected。
   2.2.7.3 如果 onFulfilled 不是一個函數并且 promise1 處于 fulfilled 狀態(tài),promise2 必須以與 promise1 同樣的 value
           轉變到 fulfilled 狀態(tài)。
   2.2.7.4 如果 onRejected 不是一個函數并且  promise1 處于 rejected狀態(tài),promise2 必須以與 promise1 同樣的 reason
           轉變到 rejected狀態(tài)。

2.3 Promise解決程序

promise解決程序是一個抽象的操作,它把一個 promise 和一個 value 作為輸入,我們將這個表示為 [[Resolve]](promise, x)。如果 x 是一個 thenable ,它將會試圖讓 promise 采用 x 的狀態(tài),前提是x的行為至少有點像一個 promise。否則,它將會用值 x 執(zhí)行 promise。
對這些 thenable 的處理使得與 promise 實現方式能夠去互相操作。只要它們公開了符合 Promise/A+ 的 then 方法。它還使得 promises/A+ 實現方式能夠采用合理的 then 方法去“同化”不一致的實現方式。
為了運行[[Resolve]](promise, x),執(zhí)行以下步驟:
2.3.1 如果 promise 與 x 是同一個對象,以 Tyeperror 作為 reason 去 reject promise。
2.3.2 如果 x 是一個 promise,使用它的狀態(tài):

   2.3.2.1 如果 x 處于 pending 狀態(tài),promise 必須保持 pending 狀態(tài)直到 x 處于 fulfilled 或者 rejected 狀態(tài)。
   2.3.2.2 如果 x 處于 fulfilled 狀態(tài),以相同的 value 去 fulfill promise。
   2.3.2.3 如果 x 處于 rejected 狀態(tài),以相同的 reason 去 reject promise。

2.3.3 否則,如果 x 是一個對象或者函數:

   2.3.3.1 讓 then 作為 x.then。
   2.3.3.2 如果取屬性 x.then 會導致拋出異常 e,則以 e 為 reason reject promise。
   2.3.3.3 如果 then 是一個函數,讓 x 作為 this 調用它,第一個參數為 resolvePromise,第二個參數為 rejectPromise,然后:
       2.3.3.3.1 如果使用value y 調用 resolvepromise 時,運行[[Resolve]](promise, y)。
       2.3.3.3.2 如果使用reason r 調用 rejectPromise 時,也用 r reject promise。
       2.3.3.3.3 如果 resolvePromise 和 rejectPromise 都被調用了,或多次調用同一參數,那么第一個調用優(yōu)先,其他的調用都會被忽略。
       2.3.3.3.4 如果調用 then 的過程中拋出了一個意外 e,
           2.3.3.3.4.1 如果 resolvePromise 或者 rejectPromise 被調用了,那么忽略它。
           2.3.3.3.4.2 否則,把 e 作為 reason reject promise。
   2.3.3.4 如果 then 不是一個函數,將 x 作為參數執(zhí)行 promise。

2.3.4 如果 x 不是一個對象或者函數,將 x 作為參數執(zhí)行 promise。

如果一個參與了 thenable 循環(huán)鏈的 thenable 去 resolve promise,這樣 [[Resolve]](promise, thenable) 的遞歸性質最終會導致 [[Resolve]](promise, thenable) 會被再次調用,遵循上述算法將會導致無限遞歸。我們鼓勵去實現(但不是必需的)檢測這樣的遞歸,并以 TypeError 作為 reason 去 reject Promise。[3.6]

注意
3.1 這里的“平臺代碼”指的是引擎,環(huán)境和 promise 實現代碼。實際上,這個要求保證了 onFulfilled 和 onRejected 將會異步執(zhí)行,在事件循環(huán)之后,用一個新的堆棧來調用它。 這可以通過“宏任務”機制(如 settimeou t或 setimmediate )或“微任務”機制(如 mutationobserver 或 process.nextick)來實現。由于 Promise 實現被視為平臺代碼,因此它本身可能包含一個任務調度隊列或“trampoline”,并在其中調用處理程序。
3.2 也就是說,在 strict 模式下,這(指的是this)在它們內部將會是 undefined;在 sloppy 模式下,它將會是全局對象。
3.3 如果實現滿足所有要求,則實現可能允許 promise2 == promise1。每個實現都應該記錄它是否能夠生成 promise2 == promise1 以及在什么條件下。
3.4 一般來說,只有當 X 來自當前的實現時,才知道它是一個真正的 promise。本條款允許使用特定于實現的方法來采用已知一致承諾的狀態(tài)。
3.5 此過程首先存儲對 x 的引用,然后測試該引用,然后調用該引用,避免多次訪問 x.then 屬性。這些預防措施對于確保訪問器屬性的一致性非常重要,訪問器屬性的值可能在兩次檢索之間發(fā)生更改。
3.6 實現方式中不應當在 thenbale 鏈中的深度設置主觀的限制,并且不應當假設鏈的深度超過主觀的限制后會是無限的。只有真正的循環(huán)才能導致 TypeError。如果遇到由無限多個不同 thenable 組成的鏈,那么永遠遞歸是正確的行為。

接下來根據規(guī)范進行手寫實現,注釋偷懶就將對應的規(guī)范標注出來,其實基本上就是對著規(guī)范實現。

function promise(fuc){ //接收一個函數作為參數
    let that = this;
    that.value = null; // 2.1.2.2
    that.reason = null;// 2.1.3.2
    that.onFulfilled = []; // 2.2.6
    that.onRejected = []; //2.2.6
    that.status = "pending"; // 2.1

    function resolve(val){
        if (that.status === "pending")
        {
            // 2.1.2
            that.status = "fulfilled";
            that.value = val; 
            that.onFulfilled.forEach(fc => fc(val)); //2.2.6.1
        }
    }
    function reject(err){
        if (that.status === "pending")
        {
            //2.1.3
            that.status = "rejected";
            that.reason = err;
            that.onRejected.forEach(fc => fc(err)); //2.2.6.2
        }
    }

    try {
        fuc(resolve,reject);
    } catch (error) {
        reject(error);
    }
}

promise.prototype.then = function (onFulfilled, onRejected) //2.2
{
    let that = this,
        promise2; //2.2.7

    onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (x) => x; //2.2.1 2.2.7.3
    onRejected = typeof onRejected === "function" ? onRejected : (e) => { throw e }; // 2.2.7.4

    switch (that.status) {
        case "pending":
            promise2 = new promise((reslove, reject)=>{
                that.onFulfilled.push(()=>{
                    setTimeout(() => {
                        try {
                            let x = onFulfilled(that.value); //2.2.2.1
                            ResolutionProcedure(promise2, x, reslove, reject); //2.2.7.1
                        } catch (err) {
                            reject(err); //2.2.7.2
                        }    
                    }, 0);
                });
                that.onRejected.push(()=>{
                    setTimeout(() => {
                        try {
                            let x = onRejected(that.reason); //2.2.3.1
                            ResolutionProcedure(promise2, x, reslove, reject); //2.2.7.1
                        } catch (err) {
                            reject(err); //2.2.7.2
                        }   
                    }, 0);
                });
            })
            break;
        case "fulfilled":
            promise2 = new promise((reslove,reject)=>{
                setTimeout(() => { // 2.2.4
                    try{
                        let x = onFulfilled(that.value); //2.2.2.1
                        ResolutionProcedure(promise2, x, reslove, reject); //2.2.7.1
                    }catch(err){
                        reject(err); //2.2.7.2
                    }    
                }, 0);
            })
            break;
        case "rejected":
            promise2 = new promise((reslove, reject)=>{
                setTimeout(() => { // 2.2.4
                    try{
                        let x = onRejected(that.reason); //2.2.3.1
                        ResolutionProcedure(promise2, x, reslove, reject); //2.2.7.1
                    }catch(err){
                        reject(err); //2.2.7.2
                    }    
                }, 0);
            })
            break;
        default:
            break;
    }

    return promise2;
}

function ResolutionProcedure(promise, x, reslove, reject){ //2.3
    if (promise === x) //2.3.1
        return reject(new TypeError("same promise"));
    if (x instanceof Promise) //2.3.2
        x.then(((xvalue)=>{
            ResolutionProcedure(promise, xvalue, reslove, reject);
        },(xreason)=>{
            reject(xreason)
        }));
    if (x !== null &&( typeof x === "object" || typeof x === "function" )) //2.3.3
    {
        try {
            let then = x.then;//2.3.3.1
            if(typeof then === "function") //2.3.3.3
            {
                let isuse = false;
                try {
                    then.call(x,(y)=>{
                        if (!isuse)
                        {   
                            ResolutionProcedure(promise, y, reslove, reject); //2.3.3.3.1
                            isuse = true;                        
                        }
                    },(r)=>{
                        if (!isuse) {
                            reject(r) //2.3.3.3.2
                            isuse = true;
                        }
                    })    
                } catch (error) {
                    if(!isuse)
                        reject(error) //2.3.3.3.4.2
                }
            }else{
                reslove(x); //2.3.3.4
            }
        } catch (error) {
            reject(error); //2.3.3.2
        }
    }else{
        reslove(x); //2.3.4
    }
}

做完之后可以通過 promise test 進行測試。
先在代碼下面加上一些測試需要代碼。

promise.deferred = function () {
    let def = {};
    def.promise = new promise(function (resolve, reject) {
        def.resolve = resolve;
        def.reject = reject;
    });
    return def;
}
module.exports = promise

然后跑一下下面的代碼即可。

npm install -g promises-aplus-tests 

promises-aplus-tests  promise.js

結果全部通過,說明符合規(guī)范:

參考:鏈接實現一個完美符合Promise/A+規(guī)范的Promise

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://systransis.cn/yun/102741.html

相關文章

  • JavaScript 異步

    摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。寫一個符合規(guī)范并可配合使用的寫一個符合規(guī)范并可配合使用的理解的工作原理采用回調函數來處理異步編程。 JavaScript怎么使用循環(huán)代替(異步)遞歸 問題描述 在開發(fā)過程中,遇到一個需求:在系統(tǒng)初始化時通過http獲取一個第三方服務器端的列表,第三方服務器提供了一個接口,可通過...

    tuniutech 評論0 收藏0
  • ES6-7

    摘要:的翻譯文檔由的維護很多人說,阮老師已經有一本關于的書了入門,覺得看看這本書就足夠了。前端的異步解決方案之和異步編程模式在前端開發(fā)過程中,顯得越來越重要。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。 JavaScript Promise 迷你書(中文版) 超詳細介紹promise的gitbook,看完再不會promise...... 本書的目的是以目前還在制定中的ECMASc...

    mudiyouyou 評論0 收藏0
  • 手寫一款符合Promise/A+規(guī)范Promise

    摘要:手寫一款符合規(guī)范的長篇預警有點長,可以選擇性觀看。初始狀態(tài)是,狀態(tài)可以有或者不能從轉換為或者從轉換成即只要由狀態(tài)轉換為其他狀態(tài)后,狀態(tài)就不可變更。 手寫一款符合Promise/A+規(guī)范的Promise 長篇預警!有點長,可以選擇性觀看。如果對Promise源碼不是很清楚,還是推薦從頭看,相信你認真從頭看到尾,并且去實際操作了,肯定會有收獲的。主要是代碼部分有點多,不過好多都是重復的,不...

    rubyshen 評論0 收藏0
  • JavaScript之手寫Promise

    摘要:如果狀態(tài)是等待態(tài)的話,就往回調函數中函數,比如如下代碼就會進入等待態(tài)的邏輯以上就是簡單版實現實現一個符合規(guī)范的接下來大部分代碼都是根據規(guī)范去實現的。 為更好的理解, 推薦閱讀Promise/A+ 規(guī)范 實現一個簡易版 Promise 在完成符合 Promise/A+ 規(guī)范的代碼之前,我們可以先來實現一個簡易版 Promise,因為在面試中,如果你能實現出一個簡易版的 Promise ...

    stefan 評論0 收藏0
  • 手寫一個符合A+規(guī)范Promise

    摘要:本文同時也發(fā)布在我的博客上,歡迎之前也手寫過簡單的,這次則是為了通過官方的測試集,借鑒了一些下載量較多的,改了幾遍,終于是通過了規(guī)范的個測試用例如何測試測試庫地址在這,大家在寫完自己的后,不妨也去測試一下,檢驗自己的是否符合規(guī)范。 本文同時也發(fā)布在我的github博客上,歡迎star~ 之前也手寫過簡單的promise,這次則是為了通過官方的Promise A+測試集,借鑒了一些下載量...

    jsummer 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<