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

資訊專欄INFORMATION COLUMN

淺析promise與自定義promise

蘇丹 / 859人閱讀

重點寫在開頭吧。
promise 簡單用法

new Promise ((res, rej) => {執(zhí)行函數(shù); res(data)}).then(data => 處理(data))

傳統(tǒng)觀念上拆分

   1. new Promise -> 實例化過程
   2.(res, rej) => {執(zhí)行函數(shù); res(data)} -> 執(zhí)行函數(shù)并拋出數(shù)據(jù)
   3.then(data => process(data)) -> 處理拋出值

但是 實際上 then 主要是用來 聲明回調(diào)函數(shù),回調(diào)函數(shù)的執(zhí)行一般都是在實例化的時候
(因為實例化傳入的函數(shù)很多都是異步,執(zhí)行慢;這有點類似于觀察者模式,在subscribe中去聲明回調(diào),真正的執(zhí)行實際上在next的時候)
所以:
一般實際執(zhí)行順序拆分(按照執(zhí)行速度拆分排序)

    1.new Promise -> 實例化過程
    2.then(data => process(data)) -> 聲明回調(diào)函數(shù)
    3.(res, rej) => {執(zhí)行函數(shù); res(data)} -> 用then 中聲明的回調(diào)函數(shù) 處理 這個res拋出的data
   

但是還有一種情況,就是實例化時候的執(zhí)行函數(shù)處理速度超過了then的聲明(按照執(zhí)行速度拆分排序)

   1. new Promise -> 實例化過程
   2.(res, rej) => {執(zhí)行函數(shù); res(data)} -> 執(zhí)行函數(shù)并拋出數(shù)據(jù),并且then尚未聲明完成
   3.then(data => process(data)) -> 直接執(zhí)行函數(shù)

簡單點說,就是實例化時候,傳入的函數(shù),和 then 聲明,到底誰先完成這是promise唯一的難點。
這么說,如果“執(zhí)行函數(shù)“ 執(zhí)行完成,執(zhí)行res(data)時,then還沒聲明完,那么回調(diào)函數(shù)就會為空,這個時候就得讓then 中 回調(diào)函數(shù)在聲明完成的之后直接執(zhí)行
亦或者 ,then 聲明完成時候,還沒有res(data), 那么就得讓then 中聲明的方法先加入到一個隊列,等待res(data)時候依次執(zhí)行;

如果這邊沒有看懂的話,可以繼續(xù)往下看。有形象化的解釋。

promise的用法簡單介紹一下,我覺得如果有人愿意看這篇文章,對promise的用法多多少少也了解;

 new Promise((res, rej) => {
        try{
            執(zhí)行函數(shù);
            res(data)
        } catch(e){
            rej(e);
        }}).then(resCb, rejCb).then(cb);

先說下我個人對promise的理解

1.promise 從表現(xiàn)形式上看,是將執(zhí)行函數(shù)的返回值通過resolve或者reject 拋出data,再在then 函數(shù)里面處理data
2.promise 可以鏈式調(diào)用then,上一個then的返回值作為下一個then中函數(shù)的實參

但實際上,promise 并非一定是在then 里面執(zhí)行的,尤其是異步的時候,理應在實例函數(shù)中執(zhí)行,才符合我們對單線程的理解。

promise簡單點說分為兩部分。一個是實例化 時候,傳入的執(zhí)行函數(shù)另一部分為then中傳入的回調(diào)函數(shù) 這個關(guān)系就好比 監(jiān)考老師學生
如果監(jiān)考老師 先到了教室,那么自然而然,學生是直接依次進入教室;(實例函數(shù)執(zhí)行較快,超過了then的聲明)
如果監(jiān)考老師 在學生們后面到,那么學生們只能按順序排隊在門口等監(jiān)考老師;(實例函數(shù)執(zhí)行較慢)
也就是說,執(zhí)行函數(shù)和then函數(shù)的聲明,先后順序并非固定(一般情況下then聲明先完成)
這個時候就需要一個狀態(tài)碼去判斷到底是哪種情況("default", "resolve" ,"reject")
為了方便理解,可以把resolve 和 reject看成同一類型
我先直接發(fā)代碼寫注釋
時間有限,本次先不考慮then 中函數(shù) 存在異步的問題

// 簡述下邏輯:
    //1.定義一個state 是用來判斷then 和 實例化時候傳入的函數(shù) 哪一個先完成
    //也就是剛剛說的監(jiān)考老師和學生的問題。默認值為default, 默認老師沒到(實例函數(shù)未執(zhí)行完成)
    //2.定義resolve_ 用來存放then 中定義的方法,相當于學生排隊的過道,便于按順序執(zhí)行,reject_同理,以下不再重復
    //3.定義resolveData用來記錄拋出值,也就是res(data) 中的data,作為then中方法的參數(shù)
    //4.在res拋出值的時候,將state改成resolve,相當于表明監(jiān)考老師到教室了
      //如果resolve_隊列中已經(jīng)有定義函數(shù)就依次執(zhí)行它們,相當于如果有學生就進教室。
    //5.then 方法聲明時候,檢測狀態(tài)state 是不是 default ,如果是,說明還沒有拋出值,
      //相當于監(jiān)考老師還沒到,學生都去排隊,加入到resolve_隊列; 
      //如果狀態(tài)已經(jīng)不是default ,那么說明監(jiān)考老師已經(jīng)到了,學生不用排隊,直接進教室;也就是方法直接執(zhí)行
  
new promise_( (res, rej) => res(3)).then(data=> {console.log(data);return 6}).then(data => console.log(data))// 3,6

針對實際例子說一下
上面的例子明顯就是 res(3) 先執(zhí)行完成,然后執(zhí)行then 的函數(shù)
相當于監(jiān)考老師先到了教室,那么,then 中的定義的函數(shù)就應該直接執(zhí)行

new promise_( (res, rej) => setTimeout( () => res(3), 1000).then(data=> {console.log(data);return 6}).then(data => console.log(data))// 3,6

上面的例子明顯就是 then 先定義完成,然后res才拋出值
相當于監(jiān)考老師后到了教室,那么,then 中的定義的函數(shù)就應該默默排隊等待

因為 then 和 實例函數(shù) 兩者順序并不確定,所以 then 時候要通過state 判斷實例函數(shù) 是否執(zhí)行完成,
同時,實例函數(shù)執(zhí)行完成拋出值時,也需要檢測一下resolve_隊列,判斷then 是否已經(jīng)聲明完成。
下面是我自己寫的promise的代碼

class promise_ {

    constructor(func) {

        if(typeof func !== "function"){
            throw Error("實例化中傳參必須為函數(shù)");
            return;
        } // 判斷下是否傳入的是函數(shù) ,與邏輯無關(guān),直接往下看

        this.state = "default"; //用來判斷
        this.resolve_ = []; // then中reslove 的方法隊列,用來接收resolve方法
        this.reject_ = []; // then中的reject 的方法隊列,用來接收reject方法
        this.resolveData = null; // resolve的拋出值
        this.rejectData = null; // reject的拋出值 

        func(this.resolve.bind(this), this.reject.bind(this)); //實例化時候傳入的函數(shù)

    }
    
    then(cb, errCb) {

        if(typeof cb !== "function" || (errCb && typeof cb !== "function")) {
            throw Error("then參數(shù),成功回調(diào)函數(shù),失敗回調(diào)函數(shù)");
            return;
        } // 日常判斷是不是傳參正確,和邏輯無關(guān)

        switch(this.state) { // 檢測一下監(jiān)考老師來沒來教室
            case "default": this.resolve_.push(cb); this.reject_.push(errCb); break;// 如果監(jiān)考老師沒到場,排隊
            case "resolve": this.resolveData = cb(this.resolveData); break; // 如果監(jiān)考老師到場,直接進來,因為鏈式調(diào)用,所以執(zhí)行后把拋出值改一下,方便后面的then 用
            case "reject": this.rejectData = errCb(this.rejectData); break;// 如果監(jiān)考老師到場,直接進來,因為鏈式調(diào)用,所以執(zhí)行后把拋出值改一下,方便后面的then 用
            default: break; 
        }

        return this; // 鏈式調(diào)用
    }

    resolve(data) {

        if(!data) return; // 判斷有無參數(shù),和邏輯無關(guān)

        this.resolveData = data; // 設(shè)定拋出值
        this.state = "resolve"; // 將狀態(tài)設(shè)置為resolve ,表示監(jiān)考老師到場了
        while(this.resolve_.length)  // 先進先出,依次執(zhí)行then 中函數(shù)
            this.resolvedata = this.resolve_.shift()(data);
    }

    reject(data) {

        if(!data) return;

        this.rejectData = data;
        this.state = "reject";
        while(this.reject_.length) 
            this.rejectData = this.reject_.shift()(data);
    }

}


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

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

相關(guān)文章

  • 淺析 Vue 2.6 中的 nextTick 方法

    摘要:核心的異步延遲函數(shù),用于異步延遲調(diào)用函數(shù)優(yōu)先使用原生原本支持更廣,但在的中,觸摸事件處理程序中觸發(fā)會產(chǎn)生嚴重錯誤的,回調(diào)被推入隊列但是隊列可能不會如期執(zhí)行。 淺析 Vue 2.6 中的 nextTick 方法。 事件循環(huán) JS 的 事件循環(huán) 和 任務隊列 其實是理解 nextTick 概念的關(guān)鍵。這個網(wǎng)上其實有很多優(yōu)質(zhì)的文章做了詳細介紹,我就簡單過過了。 以下內(nèi)容適用于瀏覽器端 JS,...

    fobnn 評論0 收藏0
  • Vue.nextTick淺析

    摘要:淺析的特點之一就是響應式,但數(shù)據(jù)更新時,并不會立即更新。盡管已經(jīng)更新,但新增的元素并不立即插入到中。實際在中,執(zhí)行了,這也是自動綁定到執(zhí)行上下文的原因。在內(nèi),使用數(shù)組保存回調(diào)函數(shù),表示當前狀態(tài),使用函數(shù)來執(zhí)行回調(diào)隊列。 Vue.nextTick 淺析 Vue 的特點之一就是響應式,但數(shù)據(jù)更新時,DOM 并不會立即更新。當我們有一個業(yè)務場景,需要在 DOM 更新之后再執(zhí)行一段代碼時,可以...

    MartinDai 評論0 收藏0
  • 淺析es6-promise源碼

    摘要:主要邏輯本質(zhì)上還是回調(diào)函數(shù)那一套。通過的判斷完成異步和同步的區(qū)分。 主要邏輯: 本質(zhì)上還是回調(diào)函數(shù)那一套。通過_subscribers的判斷完成異步和同步的區(qū)分。通過 resolve,reject -> publish -> invokeCallback -> resolve,reject的遞歸和下一條then的parent是上一條的child來完成then鏈的流轉(zhuǎn) 同步情況...

    fox_soyoung 評論0 收藏0
  • 淺析Promise

    摘要:聲明,只是簡單地提了提的基本使用,大牛繞道先看一個例子你需要知道是個庫返回一個實例你可以把理解為,它們功能相近,只不過遵循規(guī)范我是第二個我是第二個為了防止你對這個鏈式調(diào)用看得眼花繚亂,我把這個給簡化一下成功回調(diào)失敗回調(diào)成功回調(diào)失敗回調(diào),準備 聲明,只是簡單地提了提promise的基本使用,大牛繞道^_^ 1.先看一個例子 你需要知道1.axios是個庫2.axios()返回一個Prom...

    darkerXi 評論0 收藏0
  • 淺析 JS 事件循環(huán)之 Microtask 和 Macrotask

    摘要:常見應用則是為了完成一些更新應用程序狀態(tài)的較小的任務,如處理的回調(diào)和的修改,以便讓這些任務在瀏覽器重新渲染之前執(zhí)行。常見應用執(zhí)行順序的實現(xiàn)需要至少一個和至少一個。 簡介 我們在上一篇 《淺析 JS 中的EventLoop 事件循環(huán)》 中提到一個 Event Queue,其實在事件循環(huán)中 queue 一共有兩種,還有一種叫 Job Queue 其中 Event Queue 在 HTML...

    sihai 評論0 收藏0

發(fā)表評論

0條評論

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