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

資訊專欄INFORMATION COLUMN

Promise 詳解

anquan / 1910人閱讀

摘要:被觀察者管理內(nèi)部和的狀態(tài)轉(zhuǎn)變,同時(shí)通過(guò)構(gòu)造函數(shù)中傳遞的和方法以主動(dòng)觸發(fā)狀態(tài)轉(zhuǎn)變和通知觀察者。第一個(gè)回調(diào)函數(shù)是對(duì)象的狀態(tài)變?yōu)闀r(shí)調(diào)用,第二個(gè)回調(diào)函數(shù)是對(duì)象的狀態(tài)變?yōu)闀r(shí)調(diào)用可選實(shí)現(xiàn)主要實(shí)現(xiàn)第一步,初步構(gòu)建。

Promise 含義

Promise是異步編程的一種解決方案,比傳統(tǒng)的解決方案(回調(diào)函數(shù)和事件)更合合理、強(qiáng)大。所謂Promise,簡(jiǎn)單來(lái)說(shuō)就是一個(gè)容器,里面保存著某個(gè)未來(lái)才會(huì)結(jié)束的事件(通常是一個(gè)異步操作)的結(jié)果。從語(yǔ)法上說(shuō),Promies是一個(gè)對(duì)象,從它可以獲取異步操作的消息。Promise提供統(tǒng)一的API,各種異步操作都可以用同樣的方法進(jìn)行處理

Promise對(duì)象有以下兩個(gè)特點(diǎn)

對(duì)象的狀態(tài)不受外界影響。

一旦狀態(tài)改變,就不會(huì)再變,任何時(shí)候都可以得到這個(gè)結(jié)果

promise有三種狀態(tài),pending(進(jìn)行中)、fulfilled/resolved(已成功)和rejected(已失敗)

Promise優(yōu)點(diǎn)

將異步操作以同步操作的流程表達(dá)出來(lái),避免了回調(diào)地獄

Promise對(duì)象提供統(tǒng)一的接口,更加容易控制異步操作

Promise缺點(diǎn)

無(wú)法中途終止,一旦新建立即執(zhí)行

如果不設(shè)置回調(diào)函數(shù),Promise內(nèi)部拋出的錯(cuò)誤,不會(huì)反應(yīng)到外部

當(dāng)處于pending狀態(tài)時(shí),無(wú)法得知目前進(jìn)展到哪一個(gè)階段

Promise設(shè)計(jì)原理

Promise的實(shí)現(xiàn)過(guò)程,其主要使用了設(shè)計(jì)模式中的觀察者模式:

通過(guò)Promise.prototype.then和Promise.prototype.catch方法將觀察者方法注冊(cè)到被觀察者Promise對(duì)象中,同時(shí)返回一個(gè)新的Promise對(duì)象,以便可以鏈?zhǔn)秸{(diào)用。

被觀察者管理內(nèi)部pending、fulfilled和rejected的狀態(tài)轉(zhuǎn)變,同時(shí)通過(guò)構(gòu)造函數(shù)中傳遞的resolve和reject方法以主動(dòng)觸發(fā)狀態(tài)轉(zhuǎn)變和通知觀察者。

Promise 是通過(guò).then方法來(lái)實(shí)現(xiàn)多個(gè)異步操作的順序執(zhí)行
Promise的內(nèi)部也有一個(gè) defers 隊(duì)列存放事件,而 .then 方法的作用和發(fā)布訂閱模式的on方法一樣是用來(lái)訂閱事件的,每次調(diào)用 .then 方法就會(huì)往defers隊(duì)列中放入一個(gè)事件,當(dāng)異步操作完成時(shí), resolve方法標(biāo)示前一個(gè)異步過(guò)程完成并從defers隊(duì)列中取出第一個(gè)事件執(zhí)行并返回當(dāng)前對(duì)象保證鏈?zhǔn)秸{(diào)用,以此類推,就完成了所有異步過(guò)程的隊(duì)列執(zhí)行

用法
實(shí)例化Promise,返回Promise對(duì)象
const promise = new Promise(function(resolve, reject) {
  // ... some code
  if (/* 異步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

promise.then(function(value){
  // success
}, function(err){
  // failure
})

Promise對(duì)象是一個(gè)構(gòu)造函數(shù),用來(lái)生成Promise實(shí)例。通過(guò)new返回一個(gè)Promise實(shí)例
Promise構(gòu)造函數(shù)接受一個(gè)函數(shù)作為參數(shù),該函數(shù)接受resolve和reject兩個(gè)回調(diào)函數(shù)作為參數(shù),它們由 JavaScript 引擎提供,不用自己部署,用來(lái)改變Promise的狀態(tài)

resolve函數(shù),將Promise對(duì)象的狀態(tài)從 pending => resolved,在異步操作成功時(shí)調(diào)用,并將異步操作的結(jié)果,作為參數(shù)傳遞出去;

reject函數(shù),將Promise對(duì)象的狀態(tài)從 pending => rejected,在異步操作失敗時(shí)調(diào)用,并將異步操作報(bào)出的錯(cuò)誤,作為參數(shù)傳遞出去

Promise.prototype.then

then是Promise構(gòu)造函數(shù)原型鏈上的方法,Promise.prototype.then,then方法分別指定resolved狀態(tài)和rejected狀態(tài)的回調(diào)函數(shù)

then方法可以接受兩個(gè)回調(diào)函數(shù)作為參數(shù)。第一個(gè)回調(diào)函數(shù)是Promise對(duì)象的狀態(tài)變?yōu)閞esolved時(shí)調(diào)用,第二個(gè)回調(diào)函數(shù)是Promise對(duì)象的狀態(tài)變?yōu)閞ejected時(shí)調(diào)用【可選】

Promise 實(shí)現(xiàn) 主要實(shí)現(xiàn)

第一步,初步構(gòu)建。Promise 的參數(shù)是函數(shù) executor,把內(nèi)部定義 resolve 方法作為參數(shù)傳到 executor 中,調(diào)用 executor。當(dāng)異步操作成功后會(huì)調(diào)用 resolve 方法,然后就會(huì)執(zhí)行 then 中注冊(cè)的回調(diào)函數(shù);并通過(guò)then中的return this實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用

        function MyPromise(executor) {
            var value = null,
                callbacks = [];  //callbacks為數(shù)組,因?yàn)榭赡芡瑫r(shí)有很多個(gè)回調(diào)

            this.then = function (onFulfilled) {
                callbacks.push(onFulfilled);
                return this // 返回Promise對(duì)象,實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用
            };

            // 成功回調(diào)
            function resolve(value) {
                setTimeout(function() { // Promises/A+規(guī)范明確要求回調(diào)需要通過(guò)異步方式執(zhí)行,用以保證一致可靠的執(zhí)行順序;通過(guò)setTimeout機(jī)制,將resolve中執(zhí)行回調(diào)的邏輯放置到JS任務(wù)隊(duì)列末尾,以保證在resolve執(zhí)行時(shí),then方法的回調(diào)函數(shù)已經(jīng)注冊(cè)完成
                    callbacks.forEach(function (callback) {
                        callback(value);
                    });
                }, 0)
            }

            executor(resolve);
        }

第二步,添加狀態(tài)state

        function MyPromise(executor) {
            var state = "pending",
                value = null,
                callbacks = [];

            this.then = function (onFulfilled) {
                if (state === "pending") {
                    callbacks.push(onFulfilled);
                    return this;
                }
                onFulfilled(value);
                return this;
            };

            function resolve(newValue) {
                value = newValue;
                state = "fulfilled";
                setTimeout(function () {
                    callbacks.forEach(function (callback) {
                        callback(value);
                    });
                }, 0);
            }

            executor(resolve);
        }

完整實(shí)現(xiàn)代碼

        function MyPromise(executor) {
            this._status = "PENDING"
            this._value = null
            this._reason = null
            this._resolveFns = []
            this._rejectFns = []

            var handler = function(state, value) {
                if (this.state !== "PENDING") return 

                let promise = this
                let fns = []

                setTimeout(function() {
                    promise.state = state 
                    let st = state === "FULFILLED"
                    fns = st ? promise["_resolveFns"] : promise["_resolveFns"]
                    fns.forEach(fn => {
                        value = fn.call(promise, value) || value
                    })

                    promise[st ? "_value" : "_reason"] = value;
                    promise["_resolveFns"] = promise["_resolveFns"] = undefined;
                }, 0)
            }

            var resolve = function(value) {
                handler.call(this, "FULFILLED", value);
            }

            var reject = function(reason){
                handler.call(this, "REJECTED", reason);
            }
            
            executor(resolve,reject)
        }


        MyPromise.prototype.then = function(resolveFn, rejectFn) {
            var promise = this
            //串行
            return new Promise(function(resolveNext, rejectNext) {
                // 在 then 方法,對(duì)then方法的回調(diào)函數(shù)返回結(jié)果 ret 進(jìn)行判斷,如果是一個(gè) promise 對(duì)象,就會(huì)調(diào)用其 then 方法,形成一個(gè)嵌套,直到其不是promise對(duì)象為止
                function resolveHandler(value) {
                    var result = typeof resolveFn === "function" && resolveFn(value) || value 
                    if (result && typeof result.then === "function") {
                        result.then(function(value) {
                            resolveNext(value)
                        }, function(reason) {
                            rejectNext(reason)
                        })
                    } else {
                        resolveNext(result)
                    }
                }

                function rejectHandler(reason) {
                    var reason = typeof rejectFn === "function" && rejectFn(reason) || reason 
                    rejectNext(reason)
                }

                if(promise._status === "PENDING"){
                    promise._resolveFns.push(resolveHandler);
                    promise._rejectFns.push(rejectHandler);
                }else if(promise._status === "FULFILLED"){ // 狀態(tài)改變后的then操作,立刻執(zhí)行
                    resolveHandler(promise._value);
                }else if(promise._status === "REJECTED"){
                    rejectHandler(promise._reason);
                }
                
            })
        }

測(cè)試

        // 實(shí)際上,fn中的resolve、reject函數(shù)分別是then方法中對(duì)應(yīng)的函數(shù)參數(shù)
        var fn5 = function(resolve, reject){
          console.log("oooo1")
          resolve("5");
          console.log("ssss1")
        }
        var fn6 = function(resolve, reject){
          resolve("6");
        }

        new MyPromise(fn5).then(function(data){
          console.log(data);
          return new MyPromise(fn6);
        }).then(function(data){
          console.log(data);
        });
其他常用 Promise API 實(shí)現(xiàn)
MyPromise.prototype.catch = function(reject) {
            return this.then(undefined, reject)
        }

        MyPromise.prototype.delay = function(time) {
            return this.then(function(ori){
                return Promise.delay(ms, value || ori);
            })
        }

        MyPromise.delay = function(ms, value) {
            return new MyPromise(function(resolve, reject){
                setTimeout(function(){
                    resolve(value)
                }, ms)
            })
        }

        MyPromise.resolve = function(value) {
            return new MyPromise(function(resolve, reject){
                resolve(value)
            })
        }

        MyPromise.reject = function(value) {
            return new MyPromise(function(resolve, reject){
                reject(value)
            })
        }

        MyPromise.all = function(promises) {
            return new MyPromise(function(resolve, reject) {
                var result = []
                function resolver(index) {
                    return function(val) {
                        result.push(val)
                        while(--index) {
                            resolve(result)
                        }
                    }
                }

                function rejecter(reason) {
                    reject(reason)
                }

                for (var i = 0; i < promises.length; i++) {
                    promises[i].then(resolver(i), rejecter)
                }
            })
        }

        MyPromise.race = function(promises) {
            return new MyPromise(resolve, reject) {
                function resolver(val) {
                    resolve(val)
                }

                function rejecter(reason) {
                    reject(reason)
                }

                for (var i = 0; i < promises.length; i++) {
                    promises[i].then(resolver, rejecter)
                }
            }
        }
遵循Promise A+ 規(guī)范的 Promise 實(shí)現(xiàn) Promise A+ then 規(guī)范 Promise決議解決過(guò)程
    這個(gè)是將promise和一個(gè)值x作為輸入的一個(gè)抽象操作。如果這個(gè)x是支持then的,他會(huì)嘗試讓promise接受x的狀態(tài);否則,他會(huì)用x的值來(lái)fullfill這個(gè)promise。運(yùn)行這樣一個(gè)東西,遵循以下的步驟
        2.3.1 如果promise和x指向同一個(gè)對(duì)象,則reject這個(gè)promise使用TypeError。
        2.3.2 如果x是一個(gè)promise,接受他的狀態(tài)
            2.3.2.1 如果x在pending,promise必須等待x的狀態(tài)改變
            2.3.2.2 如果x被fullfill,那么fullfill這個(gè)promise使用同一個(gè)value
            2.3.2.3 如果x被reject,那么reject這個(gè)promise使用同一個(gè)理由

        2.3.3 如果x是一個(gè)對(duì)象或者是個(gè)方法
            2.3.3.1 then = x.then
            2.3.3.2 如果x.then返回了錯(cuò)誤,則reject這個(gè)promise使用錯(cuò)誤。
            2.3.3.3 如果then是一個(gè)function,使用x為this,resolvePromise為一參,rejectPromise為二參,
                2.3.3.3.1 如果resolvePromise被一個(gè)值y調(diào)用,那么運(yùn)行[[Resolve]](promise, y)
                2.3.3.3.2 如果rejectPromise被reason r,使用r來(lái)reject這個(gè)promise
                2.3.3.3.3 如果resolvePromise和rejectPromise都被調(diào)用了,那么第一個(gè)被調(diào)用的有優(yōu)先權(quán),其他的beihulue
                2.3.3.3.4 如果調(diào)用then方法得到了exception,如果上面的方法被調(diào)用了,則忽略,否則reject這個(gè)promise
            2.3.3.4 如果then方法不是function,那么fullfill這個(gè)promise使用x
        2.3.4 如果x不是一個(gè)對(duì)象或者方法,那么fullfill這個(gè)promise使用x

    如果promise產(chǎn)生了環(huán)形的嵌套,比如[[Resolve]](promise, thenable)最終喚起了[[Resolve]](promise, thenable),那么實(shí)現(xiàn)建議且并不強(qiáng)求來(lái)發(fā)現(xiàn)這種循環(huán),并且reject這個(gè)promise使用一個(gè)TypeError。
代碼實(shí)現(xiàn)
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
function Promise(executor) {
    let self = this;
    self.status = PENDING;
    self.onFulfilled = [];//成功的回調(diào)
    self.onRejected = []; //失敗的回調(diào)
    //PromiseA+ 2.1
    function resolve(value) {
        if (self.status === PENDING) {
            self.status = FULFILLED;
            self.value = value;
            self.onFulfilled.forEach(fn => fn());//PromiseA+ 2.2.6.1
        }
    }

    function reject(reason) {
        if (self.status === PENDING) {
            self.status = REJECTED;
            self.reason = reason;
            self.onRejected.forEach(fn => fn());//PromiseA+ 2.2.6.2
        }
    }

    try {
        executor(resolve, reject);
    } catch (e) {
        reject(e);
    }
}

Promise.prototype.then = function (onFulfilled, onRejected) {
    //PromiseA+ 2.2.1 / PromiseA+ 2.2.5 / PromiseA+ 2.2.7.3 / PromiseA+ 2.2.7.4
    onFulfilled = typeof onFulfilled === "function" ? onFulfilled : value => value;
    onRejected = typeof onRejected === "function" ? onRejected : reason => { throw reason };
    let self = this;
    //PromiseA+ 2.2.7
    let promise2 = new Promise((resolve, reject) => {
        if (self.status === FULFILLED) {
            //PromiseA+ 2.2.2
            //PromiseA+ 2.2.4 --- setTimeout
            setTimeout(() => {
                try {
                    //PromiseA+ 2.2.7.1
                    let x = onFulfilled(self.value);
                    resolvePromise(promise2, x, resolve, reject);
                } catch (e) {
                    //PromiseA+ 2.2.7.2
                    reject(e);
                }
            });
        } else if (self.status === REJECTED) {
            //PromiseA+ 2.2.3
            setTimeout(() => {
                try {
                    let x = onRejected(self.reason);
                    resolvePromise(promise2, x, resolve, reject);
                } catch (e) {
                    reject(e);
                }
            });
        } else if (self.status === PENDING) {
            self.onFulfilled.push(() => {
                setTimeout(() => {
                    try {
                        let x = onFulfilled(self.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                });
            });
            self.onRejected.push(() => {
                setTimeout(() => {
                    try {
                        let x = onRejected(self.reason);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                });
            });
        }
    });
    return promise2;
}

        
function resolvePromise(promise2, x, resolve, reject) {
    let self = this;
    //PromiseA+ 2.3.1
    if (promise2 === x) {
        reject(new TypeError("Chaining cycle"));
    }
    if (x && typeof x === "object" || typeof x === "function") {
        let used; //PromiseA+2.3.3.3.3 只能調(diào)用一次
        try {
            let then = x.then;
            if (typeof then === "function") {
                //PromiseA+2.3.3
                then.call(x, (y) => {
                    //PromiseA+2.3.3.1
                    if (used) return;
                    used = true;
                    resolvePromise(promise2, y, resolve, reject);
                }, (r) => {
                    //PromiseA+2.3.3.2
                    if (used) return;
                    used = true;
                    reject(r);
                });

            }else{
                //PromiseA+2.3.3.4
                if (used) return;
                used = true;
                resolve(x);
            }
        } catch (e) {
            //PromiseA+ 2.3.3.2
            if (used) return;
            used = true;
            reject(e);
        }
    } else {
        //PromiseA+ 2.3.3.4
        resolve(x);
    }
}

module.exports = Promise;

resolvePromise 函數(shù)即為根據(jù)x的值來(lái)決定promise2的狀態(tài)的函數(shù),也即標(biāo)準(zhǔn)中的Promise Resolution Procedure;x為promise2 = promise1.then(onResolved, onRejected)onResolved/onRejected的返回值,resolvereject實(shí)際上是promise2executor的兩個(gè)實(shí)參,因?yàn)楹茈y掛在其它的地方,所以一并傳進(jìn)來(lái)。

promise 總結(jié)

Promise的then方法回調(diào)是異步,構(gòu)造函數(shù)內(nèi)是同步。【內(nèi)同外異】

Promise狀態(tài)一旦改變,無(wú)法在發(fā)生變更。 pending -> fulfilled、 pending -> rejected

Promise的then方法的參數(shù)期望是函數(shù),傳入非函數(shù)則會(huì)發(fā)生值穿透。

promise 的.then或者.catch可以被調(diào)用多次,但這里 Promise 構(gòu)造函數(shù)只執(zhí)行一次。或者說(shuō) promise 內(nèi)部狀態(tài)一經(jīng)改變,并且有了一個(gè)值,那么后續(xù)每次調(diào)用.then 或者.catch都會(huì)直接拿到該值。

promise 的.then或者.catch返回promise對(duì)象【catch方法是then(null, function(error){})的語(yǔ)法糖/省略寫(xiě)法】

如果調(diào)用 then 時(shí),promise已經(jīng)成功,則執(zhí)行 onFulfilled,并將promise的值作為參數(shù)傳遞進(jìn)去。如果promise已經(jīng)失敗,那么執(zhí)行 onRejected, 并將 promise 失敗的原因作為參數(shù)傳遞進(jìn)去。如果promise的狀態(tài)是pending,需要將onFulfilled和onRejected函數(shù)存放起來(lái),等待狀態(tài)確定后,再依次將對(duì)應(yīng)的函數(shù)執(zhí)行(發(fā)布訂閱)

then 的參數(shù) onFulfilled 和 onRejected 可以缺省

promise 可以then多次,promise 的then 方法返回一個(gè) promise

如果 then 返回的是一個(gè)結(jié)果,那么就會(huì)把這個(gè)結(jié)果作為參數(shù),傳遞給下一個(gè)then的成功的回調(diào)(onFulfilled)

如果 then 中拋出了異常,那么就會(huì)把這個(gè)異常作為參數(shù),傳遞給下一個(gè)then的失敗的回調(diào)(onRejected)

如果 then 返回的是一個(gè)promise,那么需要等這個(gè)promise,那么會(huì)等這個(gè)promise執(zhí)行完,promise如果成功,就走下一個(gè)then的成功,如果失敗,就走下一個(gè)then的失敗

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/103996.html

相關(guān)文章

  • async await詳解

    摘要:本身就是的語(yǔ)法糖。類似于后面代碼會(huì)等內(nèi)部代碼全部完成后再執(zhí)行打印結(jié)果操作符用于等待一個(gè)對(duì)象。它只能在異步函數(shù)中使用。參考附在版本位中是可以直接使用的。持續(xù)更新中來(lái)點(diǎn)顆吧 async await本身就是promise + generator的語(yǔ)法糖。 本文主要講述以下內(nèi)容 async awiat 實(shí)質(zhì) async await 主要特性 async await 實(shí)質(zhì) 下面使用 pro...

    Shimmer 評(píng)論0 收藏0
  • async await詳解

    摘要:本身就是的語(yǔ)法糖。類似于后面代碼會(huì)等內(nèi)部代碼全部完成后再執(zhí)行打印結(jié)果操作符用于等待一個(gè)對(duì)象。它只能在異步函數(shù)中使用。參考附在版本位中是可以直接使用的。持續(xù)更新中來(lái)點(diǎn)顆吧 async await本身就是promise + generator的語(yǔ)法糖。 本文主要講述以下內(nèi)容 async awiat 實(shí)質(zhì) async await 主要特性 async await 實(shí)質(zhì) 下面使用 pro...

    KavenFan 評(píng)論0 收藏0
  • async await詳解

    摘要:本身就是的語(yǔ)法糖。類似于后面代碼會(huì)等內(nèi)部代碼全部完成后再執(zhí)行打印結(jié)果操作符用于等待一個(gè)對(duì)象。它只能在異步函數(shù)中使用。參考附在版本位中是可以直接使用的。持續(xù)更新中來(lái)點(diǎn)顆吧 async await本身就是promise + generator的語(yǔ)法糖。 本文主要講述以下內(nèi)容 async awiat 實(shí)質(zhì) async await 主要特性 async await 實(shí)質(zhì) 下面使用 pro...

    yedf 評(píng)論0 收藏0
  • Promise加載圖片用法詳解

    摘要:現(xiàn)在不會(huì)用都不好意思說(shuō)自己是前端,為什么火起來(lái),一句話解決了回調(diào)嵌套和執(zhí)行順序問(wèn)題最重要的我感覺(jué)是解決順序問(wèn)題。 現(xiàn)在不會(huì)用Promise都不好意思說(shuō)自己是前端,Promise為什么火起來(lái),一句話解決了回調(diào)嵌套和執(zhí)行順序問(wèn)題最重要的我感覺(jué)是解決順序問(wèn)題。 不過(guò)開(kāi)始寫(xiě)之前我們先看看,promise怎么解決問(wèn)題,怎么用。列舉一個(gè)順序加載圖片demo: //需求 加載三張圖片 img1,im...

    Brenner 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<