亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

淺析promise與自定義promise

蘇丹 / 911人閱讀

重點(diǎn)寫在開頭吧。
promise 簡單用法

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

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

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

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

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

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

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

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

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

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

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

先說下我個(gè)人對promise的理解

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

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

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

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

針對實(shí)際例子說一下
上面的例子明顯就是 res(3) 先執(zhí)行完成,然后執(zhí)行then 的函數(shù)
相當(dāng)于監(jiān)考老師先到了教室,那么,then 中的定義的函數(shù)就應(yīng)該直接執(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才拋出值
相當(dāng)于監(jiān)考老師后到了教室,那么,then 中的定義的函數(shù)就應(yīng)該默默排隊(duì)等待

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

class promise_ {

    constructor(func) {

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

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

        func(this.resolve.bind(this), this.reject.bind(this)); //實(shí)例化時(shí)候傳入的函數(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)考老師沒到場,排隊(duì)
            case "resolve": this.resolveData = cb(this.resolveData); break; // 如果監(jiān)考老師到場,直接進(jìn)來,因?yàn)殒準(zhǔn)秸{(diào)用,所以執(zhí)行后把拋出值改一下,方便后面的then 用
            case "reject": this.rejectData = errCb(this.rejectData); break;// 如果監(jiān)考老師到場,直接進(jìn)來,因?yàn)殒準(zhǔn)秸{(diào)用,所以執(zhí)行后把拋出值改一下,方便后面的then 用
            default: break; 
        }

        return this; // 鏈?zhǔn)秸{(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)  // 先進(jìn)先出,依次執(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://www.ezyhdfw.cn/yun/105091.html

相關(guān)文章

  • 淺析 Vue 2.6 中的 nextTick 方法

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

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

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

    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

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

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

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

    sihai 評論0 收藏0

發(fā)表評論

0條評論

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