国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Promise 規范解讀及實現細節 (二)

Michael_Lin / 3450人閱讀

摘要:開始前的實現原理已經在規范解讀及實現細節一中說的很清楚了,這里將詳細分析規范中的解析過程,最后會實現一個并提供用于測試的代碼方法分析這里的調用會產生一個新的不同實例對于上一級的終值會作為的參數被傳入對于如果返回一個返回一個那么的狀態和值由決

開始前

Promise的實現原理已經在 Promise 規范解讀及實現細節 (一) 中說的很清楚了,這里將詳細分析 Promises/A+規范 中的Promise解析過程,最后會實現一個 Promise 并提供用于測試的代碼

then 方法分析

promise.then(fn1).then(fn2).then(fn3) 這里 promise.then() 的調用會產生一個新的promise(不同實例)

對于 then(fn) 上一級 promise 的終值會作為 fn 的參數被傳入

對于 then(fn) 如果 then 返回一個 promise1,fn 返回一個 promise2 那么 promise1 的狀態和值由 promise2 決定

對于 then(fn) 如果 then 返回一個 promise1,fn 返回一個 promise2 我們想依賴于promise2 的調用會被添加到 promise1

如何讓 promise2 決定 promise1 的結果

如果promise2thenvar promise2Then = promise2.then,我們這樣promise2Then.bind(promise1,resolve,reject)

promise 的狀態和終值都是通過 當前 promiseresolvereject 來改變的,所以只需要將 promise1 的這兩個函數通過promise2then 方法添加的 promise2 的執行隊列中就可以達到想要的效果

Promise 解析過程

對于 promise.then(fn),then 方法返回 promise1fn 方法返回 x,fn 接收到的參數為 y,這時需要對 xy 分別運行Promise解析過程

x: [[Resolve]](promise1, x)
y: [[Resolve]](promise1, y)
x 的解析過程處理的是 回掉中返回 promise 的情況
y 的解析過程處理的是 向當前 promise 傳遞處理結果的那個 promise 的終值是 promise 的情況

由此可見 promise 的解析過程是遞歸的,遞歸的終點是 x,y 不是promise,在是對象或者函數的情形下不具備 then 方法

代碼結構
(function(window) {
    var PENDING = 0; //PENDING 狀態
    var RESOLVED = 1; //RESOLVED 狀態
    var REJECTED = 2; //REJECTED 狀態
    function IPromise(fn) {
        if (!(this instanceof IPromise)) return new IPromise(fn); //確保 通過 new IPromise() 和 IPromise() 都能正確創建對象
        var state = PENDING; //promise 狀態
        var value = null; //終值
        var callback = []; //回掉函數隊列,在一種是兩個隊列,這里是一個,所以存放的是對象

        function reject(reason) {} //reject 方法
        function resolve(result) {} //和(一)中的對比 這里多了 執行 Promise 解析過程 的功能
        function handle(handler) {} //添加或執行隊 callback 中的調用

        /**
        *@param onFulfilled 通過 then 方法添加的 onFulfilled
        *@param onRejected 通過 then 方法添加的 onRejected
        *
        *@func 包裝用戶添加的回調 
        *因為這里只有一個回掉隊列所以需要用 candy(糖果) 包裝成{onFulfilled:onFulfilled,onRejected:onRejected}
        *
        *@func 延遲調用handle
        *在 Promise 規范解讀及實現細節 (一) 中說 Promise(瀏覽器實現) 會被加入到microtask,由于瀏覽器沒有提供除Promise
        *之外microtask的接口,所以 我們要用 setTimeout 來延遲調用并添加到 macrotask
        *
        */
        function candy(onFulfilled, onRejected) {}

        function getThen(value) {} //判斷 value 是否有 then 方法如果有則獲取

        this.then = function(onFulfilled, onRejected) {} //暴露的 then 方法
        doResolve(fn, resolve, reject); //執行 fn
        window.IPromise = IPromise; //將 IPromise 添加到瀏覽器的 window 上
    }
    /**
    *Promise 解析過程
    */
    function doResolve(fn, resolvePromise, rejectPromise) {} //靜態私有方法,解析并執行promise(解析并執行fn和promise的處理結果)
})(window);

以上通過 js 自執行函數將變量和函數限制在了作用域中,在全局的 window 上只暴露一個構造函數 IPromise 保證了全局不被污染

具體代碼及解釋(請在瀏覽器中運行)
/**
 *@author ivenj
 *@date 2016-12-06
 *@version 1.0 
 */
(function(window) {
    var PENDING = 0;
    var RESOLVED = 1;
    var REJECTED = 2;

    function IPromise(fn) {
        if (!(this instanceof IPromise)) return new IPromise(fn);
        var state = PENDING;
        var value = null;
        var callback = [];

        function reject(reason) {
            state = REJECTED;
            value = reason;
            callback.forEach(handle);
            callback = null;
        }

        /**
        * 這里新增的內容是 滿足Promise解析過程時 resolve和doResolve相互調用形成遞歸
        **/
        function resolve(result) {
            try {
                var then = getThen(result);
                if (then) {
                    doResolve(then.bind(result), resolve, reject);  //aa
                    return; //這里如果 resule 是有 then 方法則執行 doResolve 并返回不執行后續代碼
                }
                //只有 result 不滿足 解析過程時執行,即遞歸終點
                state = RESOLVED;
                value = result;
                callback.forEach(handle);
                callback = null;
            } catch (e) {
                reject(e);
            }
        }

        function handle(handler) {
            if (state === PENDING) {
                callback.push(handler);
            } else {
                if (state === RESOLVED && typeof handler.onFulfilled === "function") {
                    handler.onFulfilled(value);
                }
                if (state === REJECTED && typeof handler.onRejected === "function") {
                    handler.onRejected(value);
                }
            }
        }

        function candy(onFulfilled, onRejected) {
            setTimeout(function() {
                handle({
                    onFulfilled: onFulfilled,
                    onRejected: onRejected
                });
            }, 0);
        }

        function getThen(value) {
            var type = typeof value;
            if (value && (type === "object" || type === "function")) {
                try{
                    var then = value.then;
                }catch(e){
                    reject(e);
                }
                if (typeof then === "function") {
                    return then;
                }
            }
            return null;
        }

        this.then = function(onFulfilled, onRejected) {
            var self = this;
            return new IPromise(function(resolve, reject) {
                candy(function(x) {
                    if (typeof onFulfilled === "function") {
                        try {
                            resolve(onFulfilled(x)); //cc 運行 [[Resolve]](promise, x)
                        } catch (e) {
                            reject(e);
                        }
                    } else {
                        resolve(x);
                    }
                }, function(error) {
                    if (typeof onRejected === "function") {
                        try {
                            resolve(onRejected(error));
                        } catch (e) {
                            reject(e);
                        }
                    } else {
                        reject(error);
                    }
                });
            });
        };
        doResolve(fn, resolve, reject);
    }

    /**
    *Promise 解析過程
    */
    function doResolve(fn, resolvePromise, rejectPromise) {
        var done = false; //用于保證只調用一次
        try {
            fn(function(y) {
                if (done) return;
                done = true;
                resolvePromise(y); //bb 如果 resolvePromise 以值 y 為參數被調用,則運行 [[Resolve]](promise, y)
            }, function(reason) {
                if (done) return;
                done = true;
                rejectPromise(reason);
            });
        } catch (e) {
            if (done) return;
            done = true;
            rejectPromise(e);
        }
    }
    window.IPromise = IPromise;
})(window);

這里是用于測試的代碼 讀者將以上代碼和以下代碼粘貼到瀏覽器去運行 一秒后會打印 {url: "http://ivenj_", value: 10}

function post(url, callback) {
    setTimeout(function() {
        var data = { //模擬異步處理結果
            url:url,
            value:10
        };
        callback(data);
    }, 1000);
}

var promise = IPromise(function(resolve, reject){
    post("http://ivenj_", function(data){
        resolve(data);
    });
});

promise.then(function(data){
    console.log(data);
});

Promise 實現最核心的內容是代碼中的 //aa //bb //cc 讀者需要著重體會這三處
Promise 到此已經結束

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

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/88328.html

相關文章

  • Promise 規范解讀實現細節 (一)

    摘要:宏任務和微任務這兩個是指兩個隊列,腳本整體代碼的回調及渲染都會被加入到隊列中回調瀏覽器實現回調都會被加入到隊列。 1. macrotask (宏任務)和 microtask (微任務) 這兩個是指兩個隊列,腳本整體代碼、setTimeout、setInterval、setImmediate、I/O、的回調及UI渲染都會被加入到 macrotask 隊列中, process.nextTi...

    gougoujiang 評論0 收藏0
  • 理解 Promise 的工作原理

    摘要:前兩個函數對應的兩種狀態和的回調函數。返回值是和對應的方法,但是會在下一事件循環返回。此外,在規范中,由方法生成的對象是已執行還是已拒絕,取決于由方法調用的那個回調是返回值還是拋出錯誤。但是對于其工作原理卻有些懵懂和好奇。 原文: https://blog.coding.net/blog/how-do-promises-work Javascript 采用回調函數(callback)來...

    Achilles 評論0 收藏0
  • Promises A+規范原文解讀 + es6實現(附詳細注釋)

    摘要:英文官方文檔原文前言寫本文的目的,是為了更好的理解,通過解讀翻譯原文,逐行解析原文通過代碼一行一行實現。英中原因是一個值結果表明被拒絕的原因。英中在法律允許的范圍內,組織已放棄所有版權及規范的相關或相鄰權利。 英文官方文檔原文:https://promisesaplus.com/ 前言 寫本文的目的,是為了更好的理解promise,通過解讀翻譯原文,逐行解析原文通過代碼一行一行實現。...

    v1 評論0 收藏0
  • 超詳細的webpack原理解讀

    摘要:生成文件,是模塊構建的終點,包括輸出文件與輸出路徑。這里配置了處理各模塊的,包括預處理,編譯,圖片處理。各插件對象,在的事件流中執行對應的方法。修改改成引入模塊在目錄下執行, webpack原理解讀 本文抄自《深入淺出webpack》,建議想學習原理的手打一遍,操作一遍,給別人講一遍,然后就會了在閱讀前希望您已有webpack相關的實踐經驗,不然讀了也讀不懂 本文閱讀需要幾分鐘,理解需...

    wenhai.he 評論0 收藏0
  • 一步一步實現一個符合PromiseA+規范Promise庫(2)

    摘要:我們都知道,方法中有和兩個回調函數,所以我們要處理一下這兩個回調函數。我們實現了異步調用,在方法中返回或者值,實現了方法中可以沒有回調函數也能把執行結果傳入下一次的方法中。 Hello everybody。我又來啦,還記得我們上一張實現的內容嗎? showImg(https://segmentfault.com/img/bV6UaU?w=102&h=95); 上一張我們實現了一個簡單的...

    jsliang 評論0 收藏0

發表評論

0條評論

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