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

資訊專欄INFORMATION COLUMN

Promise 規(guī)范解讀及實(shí)現(xiàn)細(xì)節(jié) (二)

Michael_Lin / 3457人閱讀

摘要:開始前的實(shí)現(xiàn)原理已經(jīng)在規(guī)范解讀及實(shí)現(xiàn)細(xì)節(jié)一中說的很清楚了,這里將詳細(xì)分析規(guī)范中的解析過程,最后會實(shí)現(xiàn)一個并提供用于測試的代碼方法分析這里的調(diào)用會產(chǎn)生一個新的不同實(shí)例對于上一級的終值會作為的參數(shù)被傳入對于如果返回一個返回一個那么的狀態(tài)和值由決

開始前

Promise的實(shí)現(xiàn)原理已經(jīng)在 Promise 規(guī)范解讀及實(shí)現(xiàn)細(xì)節(jié) (一) 中說的很清楚了,這里將詳細(xì)分析 Promises/A+規(guī)范 中的Promise解析過程,最后會實(shí)現(xiàn)一個 Promise 并提供用于測試的代碼

then 方法分析

promise.then(fn1).then(fn2).then(fn3) 這里 promise.then() 的調(diào)用會產(chǎn)生一個新的promise(不同實(shí)例)

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

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

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

如何讓 promise2 決定 promise1 的結(jié)果

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

promise 的狀態(tài)和終值都是通過 當(dāng)前 promiseresolvereject 來改變的,所以只需要將 promise1 的這兩個函數(shù)通過promise2then 方法添加的 promise2 的執(zhí)行隊列中就可以達(dá)到想要的效果

Promise 解析過程

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

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

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

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

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

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

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

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

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

具體代碼及解釋(請在瀏覽器中運(yùn)行)
/**
 *@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;
        }

        /**
        * 這里新增的內(nèi)容是 滿足Promise解析過程時 resolve和doResolve相互調(diào)用形成遞歸
        **/
        function resolve(result) {
            try {
                var then = getThen(result);
                if (then) {
                    doResolve(then.bind(result), resolve, reject);  //aa
                    return; //這里如果 resule 是有 then 方法則執(zhí)行 doResolve 并返回不執(zhí)行后續(xù)代碼
                }
                //只有 result 不滿足 解析過程時執(zhí)行,即遞歸終點(diǎn)
                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 運(yùn)行 [[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; //用于保證只調(diào)用一次
        try {
            fn(function(y) {
                if (done) return;
                done = true;
                resolvePromise(y); //bb 如果 resolvePromise 以值 y 為參數(shù)被調(diào)用,則運(yùn)行 [[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);

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

function post(url, callback) {
    setTimeout(function() {
        var data = { //模擬異步處理結(jié)果
            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 實(shí)現(xiàn)最核心的內(nèi)容是代碼中的 //aa //bb //cc 讀者需要著重體會這三處
Promise 到此已經(jīng)結(jié)束

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/88328.html

相關(guān)文章

  • Promise 規(guī)范解讀實(shí)現(xiàn)細(xì)節(jié) (一)

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

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

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

    Achilles 評論0 收藏0
  • Promises A+規(guī)范原文解讀 + es6實(shí)現(xiàn)(附詳細(xì)注釋)

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

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

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

    wenhai.he 評論0 收藏0
  • 一步一步實(shí)現(xiàn)一個符合PromiseA+規(guī)范Promise庫(2)

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

    jsliang 評論0 收藏0

發(fā)表評論

0條評論

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