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

資訊專(zhuān)欄INFORMATION COLUMN

啥?喝著闊落吃著西瓜就把Promise手寫(xiě)出來(lái)了???

idisfkj / 3587人閱讀

摘要:嗝首先,我們通過(guò)字面可以看出來(lái)是一種解決方案,而且還有兩種傳統(tǒng)的解決方案回調(diào)函數(shù)和事件,,那么我們就來(lái)先聊聊這兩種方案。

前言

雖然今年已經(jīng)18年,但是今天還是要繼續(xù)聊聊ES6的東西,ES6已經(jīng)過(guò)去幾年,可是我們對(duì)于ES6的語(yǔ)法究竟是掌握了什么程度,是了解?會(huì)用?還是精通?相信大家和我一樣都對(duì)自己有著一個(gè)提升的心,對(duì)于新玩具可不能僅僅了解,對(duì)于其中的思想才是最吸引人的,所以接下來(lái)會(huì)通過(guò)一篇文章,來(lái)讓大家對(duì)于Promise這個(gè)玩具做到精通的程度?。。?/p>

打開(kāi)一瓶冰闊落~~~

Promise
Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強(qiáng)大。它由社區(qū)最早提出和實(shí)現(xiàn),ES6將其寫(xiě)進(jìn)了語(yǔ)言標(biāo)準(zhǔn),統(tǒng)一了用法,原生提供了Promise對(duì)象。

~

首先,我們通過(guò)字面可以看出來(lái)Pormise是一種解決方案,而且還有兩種傳統(tǒng)的解決方案·回調(diào)函數(shù)事件,ok,那么我們就來(lái)先聊聊這兩種方案。

回調(diào)函數(shù) Callback

回調(diào)函數(shù)想必大家都不陌生,就是我們常見(jiàn)的把一個(gè)函數(shù)當(dāng)做參數(shù)傳遞給另外一個(gè)函數(shù),在滿(mǎn)足了一定的條件之后再去執(zhí)行回調(diào),比如我們想要實(shí)現(xiàn)一個(gè)在三秒后去計(jì)算1到5的和,那么:

    // 求和函數(shù)
    function sum () {
        return eval([...arguments].join("+"))
    }
    // 三秒后執(zhí)行函數(shù)
    function asycnGetSum (callback) {
        setTimeout(function(){
            var result = callback(1,2,3,4,5);
            console.log(result)
        },3000)
    }
    asyncGetSum(sum);

這樣的實(shí)現(xiàn)就是回調(diào)函數(shù),但是如果我要實(shí)現(xiàn)在一段動(dòng)畫(huà),動(dòng)畫(huà)的執(zhí)行過(guò)程是小球先向右移動(dòng)100px,然后再向下移動(dòng)100px,在向左移動(dòng)100px,每段動(dòng)畫(huà)持續(xù)時(shí)間都是3s.

    dom.animate({left:"100px"},3000,"linear",function(){
        dom.animate({top:"100px"},3000,"linear",function(){
            dom.animate({left:"0px"},3000,"linear",function(){
                console.log("動(dòng)畫(huà) done")
            })
        })
    })

這樣就會(huì)看到形成了一個(gè)回調(diào)嵌套,也就是我們常說(shuō)的回調(diào)地獄,導(dǎo)致代碼可讀性十分差。

事件

事件處理就是jQuery中的on綁定事件和trigger觸發(fā)事件,其實(shí)就是我們常見(jiàn)的發(fā)布訂閱模式,當(dāng)我訂閱了一個(gè)事件,那么我就是訂閱者,如果發(fā)布者發(fā)布了數(shù)據(jù)之后,那么我就要收到相應(yīng)的通知。

    // 定義一個(gè)發(fā)布中心
    let publishCenter = {
        subscribeArrays:{}, // 定義一個(gè)訂閱者回調(diào)函數(shù)callback
        subscribe:function(key,callback){
            // 增加訂閱者
            if(!this.subscribeArrays[key]){
                this.subscribeArrays[key] = [];
            }
            this.subscribeArrays[key].push(callback)
        },
        publish:function(){
            //發(fā)布 第一個(gè)參數(shù)是key
            let params = [...arguments];
            let key = params.shift();
            let callbacks = this.subscribeArrays[key];
            if(!callbacks || callbacks.length === 0){
                // 如果沒(méi)人訂閱 那么就返回
                return false
            }
            for( let i = 0 ; i < callbacks.length; i++ ){
                callbacks[i].apply( this, params );
            }
        }
    };
    
    // 訂閱 一個(gè)wantWatermelon事件
    publishCenter.subscribe("wantWatermelon",function(){console.log("恰西瓜咯~~")})
    
    //觸發(fā)wantWatermelon事件 好咯 可以看到 恰西瓜咯
    publishCenter.publish("wantWatermelon")

恰西瓜中~~~

Promise A+

嗝~ok,吃完我們進(jìn)入正題,看到上面異步編程如此如此如此麻煩,對(duì)于我這種頭大用戶(hù),當(dāng)然是拒絕的啊,還好我們有PormisePormise大法好),下面我們就來(lái)通過(guò)實(shí)現(xiàn)一個(gè)Promise去更深的了解Promise的原理,首先我們了解一下PromiseA+,它是一種規(guī)范,用來(lái)約束大家寫(xiě)的Promise方法的,為了讓大家寫(xiě)的Promise杜絕一些錯(cuò)誤,按照我們所期望的流程來(lái)走,因此就出現(xiàn)了PromiseA+規(guī)范。

Promise特點(diǎn)

我們根據(jù)PromiseA+文檔來(lái)一步一步的看Promise有什么特點(diǎn)。

首先我們看文檔的2.1節(jié),題目是Promise states,也就是說(shuō)講的是Promise的狀態(tài),那么都說(shuō)了些什么呢,我們來(lái)看一哈:

一個(gè)promise只有三種狀態(tài),pending態(tài),fulfilled態(tài)(完成態(tài)),rejected(拒絕態(tài))

當(dāng)promise處于pending態(tài)時(shí),可能轉(zhuǎn)化成fulfilled或者rejected

一旦promise的狀態(tài)改成了fulfilled后,狀態(tài)就不能再改變了,并且需要提供一個(gè)不可變的value

一旦promise的狀態(tài)改成了rejected后,狀態(tài)就不能再改變了,并且需要提供一個(gè)不可變的reason

ok,那么我們就開(kāi)始寫(xiě)我們自己的Promise,我們先看看一段正常Promise的寫(xiě)法

    // 成功或者失敗是需要提供一個(gè)value或者reason
    let promise1 = new Promise((resolve,rejected)=>{
        // 可以發(fā)現(xiàn) 當(dāng)我們new Promise的時(shí)候這句話(huà)是同步執(zhí)行的 也就是說(shuō)當(dāng)我們初始化一個(gè)promise的時(shí)候 內(nèi)部的回調(diào)函數(shù)(通常我們叫做執(zhí)行器executor)會(huì)立即執(zhí)行
        console.log("hahahha");
        // promise內(nèi)部支持異步
        setTimeout(function(){
            resolve(123);
        },100)
        // throw new Error("error") 我們也可以在執(zhí)行器內(nèi)部直接拋出一個(gè)錯(cuò)誤 這時(shí)promise會(huì)直接變成rejected態(tài)
    })
    

根據(jù)我們上面的代碼還有PromiseA+規(guī)范中的狀態(tài)說(shuō)明,我們可以知道Promise已經(jīng)有了下面幾個(gè)特點(diǎn)

promise有三種狀態(tài) 默認(rèn)pending態(tài) pending可以變成fulfilled(成功態(tài))或者rejected(失敗態(tài)),而一旦轉(zhuǎn)變之后就不能在變成其他值了

promise內(nèi)部有一個(gè)value 用來(lái)存儲(chǔ)成功態(tài)的結(jié)果

promise內(nèi)部有一個(gè)reason 用來(lái)存儲(chǔ)失敗態(tài)的原因

promise接受一個(gè)executor函數(shù),這個(gè)函數(shù)有兩個(gè)參數(shù),一個(gè)是resolve方法,一個(gè)是reject方法,當(dāng)執(zhí)行resolve時(shí),promise狀態(tài)改變?yōu)?b>fulfilled,執(zhí)行reject時(shí),promise狀態(tài)改變?yōu)?b>rejected

默認(rèn) new Promise 執(zhí)行的時(shí)候內(nèi)部的executor函數(shù)執(zhí)行

promise內(nèi)部支持異步改變狀態(tài)

promise內(nèi)部支持拋出異常,那么該promise的狀態(tài)直接改成rejected

我們接下來(lái)繼續(xù)看PromiseA+文檔:

promise必須要有一個(gè)then方法,用來(lái)訪(fǎng)問(wèn)它當(dāng)前的value或者是reason

該方法接受兩個(gè)參數(shù)onFulfilled(成功回掉函數(shù)),onRejected(失敗回調(diào)函數(shù)) promise.then(onFulfilled, onRejected)

這兩個(gè)參數(shù)都是可選參數(shù),如果發(fā)現(xiàn)這兩個(gè)參數(shù)不是函數(shù)類(lèi)型的話(huà),那么就忽略 比如 promise.then().then(data=>console.log(data),err=>console.log(err)) 就可以形成一個(gè)值穿透

onFulfilled必須在promise狀態(tài)改成fulfilled之后改成調(diào)用,并且呢promise內(nèi)部的value值是這個(gè)函數(shù)的參數(shù),而且這個(gè)函數(shù)不能重復(fù)調(diào)用

onRejected必須在promise狀態(tài)改成rejected之后改成調(diào)用,并且呢promise內(nèi)部的reason值是這個(gè)函數(shù)的參數(shù),而且這個(gè)函數(shù)不能重復(fù)調(diào)用

onFulfilledonRejected這兩個(gè)方法必須要在當(dāng)前執(zhí)行棧的上下文執(zhí)行完畢后再調(diào)用,其實(shí)就是事件循環(huán)中的微任務(wù)(setTimeout是宏任務(wù),有一定的差異)

onFulfilledonRejected這兩個(gè)方法必須通過(guò)函數(shù)調(diào)用,也就是說(shuō) 他們倆不是通過(guò)this.onFulfilled()或者this.onRejected()調(diào)用,直接onFulfilled()或者onRejected()

then方法可以在一個(gè)promise上多次調(diào)用,也就是我們常見(jiàn)的鏈?zhǔn)秸{(diào)用

如果當(dāng)前promise的狀態(tài)改成了fulfilled那么就要按照順序依次執(zhí)行then方法中的onFulfilled回調(diào)

如果當(dāng)前promise的狀態(tài)改成了rejected那么就要按照順序依次執(zhí)行then方法中的onRejected回調(diào)

then方法必須返回一個(gè)promise(接下來(lái)我們會(huì)把這個(gè)promise稱(chēng)做promise2),類(lèi)似于 promise2 = promise1.then(onFulfilled, onRejected);

如果呢onFulfilled()或者onRejected()任一一個(gè)返回一個(gè)值x,那么就要去執(zhí)行resolvePromise這個(gè)函數(shù)中去(這個(gè)函數(shù)是用來(lái)處理返回值x遇到的各種值,然后根據(jù)這些值去決定我們剛剛then方法中onFulfilled()或者onRejected()這兩個(gè)回調(diào)返回的promise2的狀態(tài))

如果我們?cè)?b>then中執(zhí)行onFulfilled()或者onRejected()方法時(shí)產(chǎn)生了異常,那么就將promise2用異常的原因ereject

如果onFulfilled或者onRejected不是函數(shù),并且promise的狀態(tài)已經(jīng)改成了fulfilled或者rejected,那么就用同樣的value或者reason去更新promise2的狀態(tài)(其實(shí)這一條和第三條一個(gè)道理,也就是值得穿透問(wèn)題)

好吧,我們總結(jié)了這么多規(guī)范特點(diǎn),那么我們就用這些先來(lái)練練手

    /**
     * 實(shí)現(xiàn)一個(gè)PromiseA+
     * @description 實(shí)現(xiàn)一個(gè)簡(jiǎn)要的promise
     * @param {Function} executor 執(zhí)行器
     * @author Leslie
     */
    function Promise(executor){
        let self = this;
        self.status = "pending"; // 存儲(chǔ)promise狀態(tài) pending fulfilled rejected.
        self.value = undefined; // 存儲(chǔ)成功后的值
        self.reason = undefined; // 記錄失敗的原因
        self.onfulfilledCallbacks = []; //  異步時(shí)候收集成功回調(diào)
        self.onrejectedCallbacks = []; //  異步時(shí)候收集失敗回調(diào)
        function resolve(value){
            if(self.status === "pending"){
                self.status = "fulfilled";// resolve的時(shí)候改變promise的狀態(tài)
                self.value = value;//修改成功的值
                // 異步執(zhí)行后 調(diào)用resolve 再把存儲(chǔ)的then中的成功回調(diào)函數(shù)執(zhí)行一遍
                self.onfulfilledCallbacks.forEach(element => {
                    element()
                });
            }
        }
        function reject(reason){
            if(self.status === "pending"){
                self.status = "rejected";// reject的時(shí)候改變promise的狀態(tài)
                self.reason = reason; // 修改失敗的原因
                // 異步執(zhí)行后 調(diào)用reject 再把存儲(chǔ)的then中的失敗回調(diào)函數(shù)執(zhí)行一遍
                self.onrejectedCallbacks.forEach(element => {
                    element()
                });
            }
        }
        // 如果執(zhí)行器中拋出異常 那么就把promise的狀態(tài)用這個(gè)異常reject掉
        try {
            //執(zhí)行 執(zhí)行器
            executor(resolve,reject);
        } catch (error) {
            reject(error)
        }
    }

    Promise.prototype.then = function(onfulfilled,onrejected){
        // onfulfilled then方法中的成功回調(diào)
        // onrejected then方法中的失敗回調(diào)
        let self = this;
        // 如果onfulfilled不是函數(shù) 那么就用默認(rèn)的函數(shù)替代 以便達(dá)到值穿透
        onfulfilled = typeof onfulfilled === "function"?onfulfilled:val=>val;
        // 如果onrejected不是函數(shù) 那么就用默認(rèn)的函數(shù)替代 以便達(dá)到值穿透
        onrejected = typeof onrejected === "function"?onrejected: err=>{throw err}
        let promise2 = new Promise((resolve,reject)=>{
            if(self.status === "fulfilled"){
                // 加入setTimeout 模擬異步
                // 如果調(diào)用then的時(shí)候promise 的狀態(tài)已經(jīng)變成了fulfilled 那么就調(diào)用成功回調(diào) 并且傳遞參數(shù)為 成功的value
                setTimeout(function(){
                    // 如果執(zhí)行回調(diào)發(fā)生了異常 那么就用這個(gè)異常作為promise2的失敗原因
                    try {
                        // x 是執(zhí)行成功回調(diào)的結(jié)果
                        let x = onfulfilled(self.value);
                        // 調(diào)用resolvePromise函數(shù) 根據(jù)x的值 來(lái)決定promise2的狀態(tài)
                        resolvePromise(promise2,x,resolve,reject);
                    } catch (error) {
                        reject(error)
                    }
                },0)
                
            }
        
            if(self.status === "rejected"){
                // 加入setTimeout 模擬異步
                // 如果調(diào)用then的時(shí)候promise 的狀態(tài)已經(jīng)變成了rejected 那么就調(diào)用失敗回調(diào) 并且傳遞參數(shù)為 失敗的reason
                setTimeout(function(){
                    // 如果執(zhí)行回調(diào)發(fā)生了異常 那么就用這個(gè)異常作為promise2的失敗原因
                    try {
                        // x 是執(zhí)行失敗回調(diào)的結(jié)果
                        let x = onrejected(self.reason);
                         // 調(diào)用resolvePromise函數(shù) 根據(jù)x的值 來(lái)決定promise2的狀態(tài)
                        resolvePromise(promise2,x,resolve,reject);
                    } catch (error) {
                        reject(error)
                    }
                    
                },0)
            }
        
            if(self.status === "pending"){
                //如果調(diào)用then的時(shí)候promise的狀態(tài)還是pending,說(shuō)明promsie執(zhí)行器內(nèi)部的resolve或者reject是異步執(zhí)行的,那么就需要先把then方法中的成功回調(diào)和失敗回調(diào)存儲(chǔ)襲來(lái),等待promise的狀態(tài)改成fulfilled或者rejected時(shí)候再按順序執(zhí)行相關(guān)回調(diào)
                self.onfulfilledCallbacks.push(()=>{
                    //setTimeout模擬異步
                    setTimeout(function(){
                        // 如果執(zhí)行回調(diào)發(fā)生了異常 那么就用這個(gè)異常作為promise2的失敗原因
                        try {
                             // x 是執(zhí)行成功回調(diào)的結(jié)果
                            let x = onfulfilled(self.value)
                            // 調(diào)用resolvePromise函數(shù) 根據(jù)x的值 來(lái)決定promise2的狀態(tài)
                            resolvePromise(promise2,x,resolve,reject);
                        } catch (error) {
                            reject(error)
                        }
                    },0)
                })
                self.onrejectedCallbacks.push(()=>{
                    //setTimeout模擬異步
                    setTimeout(function(){
                        // 如果執(zhí)行回調(diào)發(fā)生了異常 那么就用這個(gè)異常作為promise2的失敗原因
                        try {
                             // x 是執(zhí)行失敗回調(diào)的結(jié)果
                            let x = onrejected(self.reason)
                             // 調(diào)用resolvePromise函數(shù) 根據(jù)x的值 來(lái)決定promise2的狀態(tài)
                            resolvePromise(promise2,x,resolve,reject);
                        } catch (error) {
                            reject(error)
                        }
                    },0)
                })
            }
        })
        return promise2;
    }

一氣呵成,是不是覺(jué)得之前總結(jié)出的特點(diǎn)十分有效,對(duì)著特點(diǎn)十分順暢的就擼完了代碼~

那么就讓我們接著來(lái)看看promiseA+文檔里還有些什么內(nèi)容吧

resolvePromise這個(gè)函數(shù)呢會(huì)決定promise2用什么樣的狀態(tài),如果x是一個(gè)普通值,那么就直接采用x,如果x是一個(gè)promise那么就將這個(gè)promise的狀態(tài)當(dāng)成是promise2的狀態(tài)

判斷如果xpromise2是一個(gè)對(duì)象,即promise2 === x,那么就陷入了循環(huán)調(diào)用,這時(shí)候promise2就會(huì)以一個(gè)TypeErrorreason轉(zhuǎn)化為rejected

如果x是一個(gè)promise,那么promise2就采用x的狀態(tài),用和x相同的valueresolve,或者用和x相同的reasonreject

如果x是一個(gè)對(duì)象或者是函數(shù) 那么就先執(zhí)行let then = x.then

如果x不是一個(gè)對(duì)象或者函數(shù) 那么就resolve 這個(gè)x

如果在執(zhí)行上面的語(yǔ)句中報(bào)錯(cuò)了,那么就用這個(gè)錯(cuò)誤原因去reject promise2

如果then是一個(gè)函數(shù),那么就執(zhí)行then.call(x,resolveCallback,rejectCallback)

如果then不是一個(gè)函數(shù),那么就resolve這個(gè)x

如果xfulfilled態(tài) 那么就會(huì)走resolveCallback這個(gè)函數(shù),這時(shí)候就默認(rèn)把成功的value作為參數(shù)y傳遞給resolveCallback,即y=>resolvePromise(promise2,y),繼續(xù)調(diào)用resolvePromise這個(gè)函數(shù) 確保 返回值是一個(gè)普通值而不是promise

如果xrejected態(tài) 那么就把這個(gè)失敗的原因reason作為promise2的失敗原因reject出去

如果resolveCallback,rejectCallback這兩個(gè)函數(shù)已經(jīng)被調(diào)用了,或者多次被相同的參數(shù)調(diào)用,那么就確保只調(diào)第一次,剩下的都忽略掉

如果調(diào)用then拋出異常了,并且如果resolveCallback,rejectCallback這兩個(gè)函數(shù)已經(jīng)被調(diào)用了,那么就忽略這個(gè)異常,否則就用這個(gè)異常作為promise2reject原因

我們又又又又又又總結(jié)了這么多,好吧不說(shuō)了總結(jié)多少就開(kāi)擼吧。

/**
 * 用來(lái)處理then方法返回結(jié)果包裝成promise 方便鏈?zhǔn)秸{(diào)用
 * @param {*} promise2 then方法執(zhí)行產(chǎn)生的promise 方便鏈?zhǔn)秸{(diào)用
 * @param {*} x then方法執(zhí)行完成功回調(diào)或者失敗回調(diào)后的result
 * @param {*} resolve 返回的promise的resolve方法 用來(lái)更改promise最后的狀態(tài)
 * @param {*} reject 返回的promise的reject方法 用來(lái)更改promise最后的狀態(tài)
 */
function resolvePromise(promise2,x,resolve,reject){
    // 首先判斷x和promise2是否是同一引用 如果是 那么就用一個(gè)類(lèi)型錯(cuò)誤作為Promise2的失敗原因reject
    if( promise2 === x) return reject(new TypeError("typeError:大佬,你循環(huán)引用了!"));
    // called 用來(lái)記錄promise2的狀態(tài)改變,一旦發(fā)生改變了 就不允許 再改成其他狀態(tài)
    let called;
    if( x !== null && ( typeof x === "object" || typeof x === "function")){
        // 如果x是一個(gè)對(duì)象或者函數(shù) 那么他就有可能是promise 需要注意 null typeof也是 object 所以需要排除掉
        //先獲得x中的then 如果這一步發(fā)生異常了,那么就直接把異常原因reject掉
        try {
            let then = x.then;//防止別人瞎寫(xiě)報(bào)錯(cuò)
            if(typeof then === "function"){
                //如果then是個(gè)函數(shù) 那么就調(diào)用then 并且把成功回調(diào)和失敗回調(diào)傳進(jìn)去,如果x是一個(gè)promise 并且最終狀態(tài)時(shí)成功,那么就會(huì)執(zhí)行成功的回調(diào),如果失敗就會(huì)執(zhí)行失敗的回調(diào)如果失敗了,就把失敗的原因reject出去,做為promise2的失敗原因,如果成功了那么成功的value時(shí)y,這個(gè)y有可能仍然是promise,所以需要遞歸調(diào)用resolvePromise這個(gè)方法 直達(dá)返回值不是一個(gè)promise
                then.call(x,y => {
                    if(called) return;
                    called = true;
                    resolvePromise(promise2,y,resolve,reject)
                }, error=>{
                    if(called) return
                    called = true;
                    reject(error)
                })
            }else{
                resolve(x)
            }
        } catch (error) {
            if(called) return
            called = true;
            reject(error)
        }
    }else{
        // 如果是一個(gè)普通值 那么就直接把x作為promise2的成功value resolve掉
        resolve(x)
    }

}

finnnnnnnnnally,我們終于通過(guò)我們的不懈努力實(shí)現(xiàn)了一個(gè)基于PromiseA+規(guī)范的Promise!

最后呢為了完美,我們還要在這個(gè)promise上實(shí)現(xiàn)Promise.resolve,Promise.reject,以及catch,Promise.allPromise.race這些方法。

Promise的一些方法
Promise.resolve = function(value){
    return new Promise((resolve,reject)=>{
        resolve(value)
    })
}
Promise.reject = function(reason){
    return new Promise((resolve,reject)=>{
        reject(reason)
    })
}
Promise.prototype.catch = function(onRejected){
    return this.then(null,onRejected)
}
Promise.all = function(promises){
    return new Promise((resolve,reject)=>{
        let arr = [];
        let i = 0;
        function getResult(index,value){
            arr[index] = value;
            if(++i == promises.length) {
                resolve(arr)
            }
        }
        for(let i = 0;i{
                getResult(i,data)
            },reject)
        }
    })
}
Promise.race = function(promises){
    return new Promise((resolve,reject)=>{
        for(let i = 0 ; i < promises.length ; i++){
            promises[i].then(resolve,reject)
        }
    })
}
Promise 語(yǔ)法糖

恰完西瓜來(lái)口糖,語(yǔ)法糖是為了讓我們書(shū)寫(xiě)promise的時(shí)候能夠更加的快速,所以做了一層改變,我們來(lái)看一個(gè)例子,比如當(dāng)我們封裝一個(gè)異步讀取圖片的寬高函數(shù)

    // 原來(lái)的方式
    let getImgWidthHeight = function(imgUrl){
        return new Promise((resolve,reject)=>{
            let img = new Image();
            img.onload = function(){
                resolve(img.width+"-"+img.height)
            }
            img.onerror = function(e){
                reject(e)
            }
            img.src = imgUrl;
        })
    }

是不是覺(jué)得怎么寫(xiě)起來(lái)有點(diǎn)舒服但又有點(diǎn)不舒服,好像我每次都要去寫(xiě)執(zhí)行器啊!為什么!好的,沒(méi)有為什么,既然不舒服 我們就改!

// 實(shí)現(xiàn)一個(gè)promise的語(yǔ)法糖
Promise.defer = Promise.deferred = function (){
    let dfd = {};
    dfd.promise = new Promise((resolve,reject)=>{
        dfd.resolve = resolve;
        dfd.reject = reject;
    })
    return dfd
}

有了上面的語(yǔ)法糖我們?cè)倏匆幌履莻€(gè)圖片的函數(shù)怎么寫(xiě)

    let newGetImgWidthHeight = function(imgUrl){
        let dfd = Promise.defer();
        let img = new Image();
        img.onload = function(){
            dfd.resolve(img.width+"-"+img.height)
        }
        img.onerror = function(e){
            dfd.reject(e)
        }
        img.url = imgUrl;
        return dfd.promise
    }

是不是發(fā)現(xiàn)我們少了一層函數(shù)嵌套,呼 得勁

最終檢測(cè)
npm install promises-aplus-tests -g

既然我們都說(shuō)了我們是遵循promiseA+規(guī)范的,那至少要拿出點(diǎn)證據(jù)來(lái)是不是,不然是不是說(shuō)服不了大家,那么我們就用promises-aplus-tests這個(gè)包來(lái)檢測(cè)我們寫(xiě)的promise究竟怎么樣呢!安裝完成之后來(lái)跑一下我們的promise

最終跑出來(lái)我們?nèi)客ㄟ^(guò)測(cè)試!酷!晚餐再加個(gè)雞腿~

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

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

相關(guān)文章

  • Promise快速入門(mén)

    摘要:周五就想寫(xiě)這篇文章,但是無(wú)奈花花世界的誘惑太多就一直拖到了今天,自責(zé)遍進(jìn)入正題對(duì)象用于表示一個(gè)異步操作的最終狀態(tài)完成或失敗,以及其返回的值。 周五就想寫(xiě)這篇文章,但是無(wú)奈花花世界的誘惑太多……就一直拖到了今天,自責(zé)1e4遍;進(jìn)入正題Promise: Promise 對(duì)象用于表示一個(gè)異步操作的最終狀態(tài)(完成或失敗),以及其返回的值。 上為MDNPromise的定義;ES6規(guī)定Promis...

    bergwhite 評(píng)論0 收藏0
  • JS手寫(xiě)bind之處理new的情況詳解

      你有遇見(jiàn)過(guò)給bind返回的函數(shù)做new操作的場(chǎng)景,本篇主要講述的就是實(shí)現(xiàn)一下兼容new操作的bind寫(xiě)法,順便學(xué)習(xí)一下new操作符,為大家提供下參考?! 〈蠹铱梢匀タ聪玛P(guān)于 JS 中 bind 方法的實(shí)現(xiàn)的文章,并給出了實(shí)現(xiàn):  Function.prototype.myBind=function(thisArg,...prefixArgs){   constfn=this;   return...

    3403771864 評(píng)論0 收藏0
  • 只會(huì)用就out,手寫(xiě)一個(gè)符合規(guī)范的Promise

    摘要:傳入的回調(diào)函數(shù)也不是一個(gè)函數(shù)類(lèi)型,那怎么辦規(guī)范中說(shuō)忽略它就好了。因此需要判斷一下回調(diào)函數(shù)的類(lèi)型,如果明確是個(gè)函數(shù)再執(zhí)行它。 Promise是什么 所謂Promise,簡(jiǎn)單說(shuō)就是一個(gè)容器,里面保存著某個(gè)未來(lái)才會(huì)結(jié)束的事件(通常是一個(gè)異步操作)的結(jié)果。從語(yǔ)法上說(shuō),Promise 是一個(gè)對(duì)象,從它可以獲取異步操作的消息。Promise 提供統(tǒng)一的 API,各種異步操作都可以用同樣的方法進(jìn)行處...

    muzhuyu 評(píng)論0 收藏0
  • 2019-我的前端面試題

    摘要:先說(shuō)下我面試情況,我一共面試了家公司。篇在我面試的眾多公司里,只有同城的面問(wèn)到相關(guān)問(wèn)題,其他公司壓根沒(méi)問(wèn)。我自己回答的是自己開(kāi)發(fā)組件面臨的問(wèn)題。完全不用擔(dān)心對(duì)方到時(shí)候打電話(huà)核對(duì)的問(wèn)題。 2019的5月9號(hào),離發(fā)工資還有1天的時(shí)候,我的領(lǐng)導(dǎo)親切把我叫到辦公室跟我說(shuō):阿郭,我們公司要倒閉了,錢(qián)是沒(méi)有的啦,為了不耽誤你,你趕緊出去找工作吧。聽(tīng)到這話(huà),我虎軀一震,這已經(jīng)是第2個(gè)月沒(méi)工資了。 公...

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

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

0條評(píng)論

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