1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢
      選擇下列產(chǎn)品馬上在線溝通
      服務(wù)時間:8:30-17:00
      你可能遇到了下面的問題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
      如何從零開始利用js手寫一個Promise庫詳解

      前言

      網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)!專注于網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、微信小程序開發(fā)、集團企業(yè)網(wǎng)站建設(shè)等服務(wù)項目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了徐匯免費建站歡迎大家使用!

      ECMAScript 是 JavaScript 語言的國際標(biāo)準(zhǔn),JavaScript 是 ECMAScript 的實現(xiàn)。ES6 的目標(biāo),是使得 JavaScript 語言可以用來編寫大型的復(fù)雜的應(yīng)用程序,成為企業(yè)級開發(fā)語言。

      概念

      ES6 原生提供了 Promise 對象。

      所謂 Promise,就是一個對象,用來傳遞異步操作的消息。它代表了某個未來才會知道結(jié)果的事件(通常是一個異步操作),并且這個事件提供統(tǒng)一的 API,可供進(jìn)一步處理。

      三道思考題

      剛開始寫前端的時候,處理異步請求經(jīng)常用callback,簡單又順手。后來寫著寫著就拋棄了callback,開始用promise來處理異步問題。promise寫起來確實更加優(yōu)美,但由于缺乏對它內(nèi)部結(jié)構(gòu)的深刻認(rèn)識,每次在遇到一些復(fù)雜的情況時,promise用起來總是不那么得心應(yīng)手,debug也得搞半天。

      所以,這篇文章我會帶大家從零開始,手寫一個基本能用的promise。跟著我寫下來以后,你會對promise是什么以及它的內(nèi)部結(jié)構(gòu)有一個清楚的認(rèn)知,未來在復(fù)雜場景下使用promise也能如魚得水。

      而且,為了檢驗大家是否真的完全掌握了promise,我會在文章結(jié)尾出幾道跟promise相關(guān)的練習(xí)題。說是練習(xí)題,其實都是大家項目中會遇到的真實場景的抽象,熟練掌握可以幫助大家在前端方面更上一層樓。

      提前將三道練習(xí)題給出來,大家可以先不看下文的內(nèi)容,在腦海里大概構(gòu)思下你會怎么解決:

      • promise array的鏈?zhǔn)秸{(diào)用?
      • promise怎么做并發(fā)控制?
      • promise怎么做異步緩存?

      以上三道思考題其實跟你用不用promise并沒有多大關(guān)系,但是如果你不深刻理解promise想要解決這三個問題還真不是那么輕松的。

      什么是Promise

      回到正文,什么是Promise?說白了,promise就是一個容器,里面保存著某個未來才會結(jié)束的事件(通常是一個異步操作)的結(jié)果。

      首先,ES6規(guī)定Promise對象是一個構(gòu)造函數(shù),用來生成Promise實例。然后,這個構(gòu)造函數(shù)接受一個函數(shù)(executor)作為參數(shù),該函數(shù)的兩個參數(shù)分別是resolve和reject。最后,Promise實例生成以后,可以用then方法分別指定resolved狀態(tài)和rejected狀態(tài)的回調(diào)函數(shù)(onFulfilled和onRejected)。

      具體的使用方法,用代碼表現(xiàn)是這樣:

      const promise = new Promise(function(resolve, reject) {
       // ... some code
      
       if (/* 異步操作成功 */){
       resolve(value);
       } else {
       reject(error);
       }
      });
      
      promise.then(function(value) {
       // success
      }, function(error) {
       // failure
      });

      理解了這個后,我們就可以大膽的開始構(gòu)造我們自己的promise了,我們給它取個名字:CutePromise

      實現(xiàn)一個Promise:CutePromise

      我們直接用ES6的class來創(chuàng)建我們的CutePromise,對ES6語法還不熟悉的,可以先讀一下我的另外兩篇介紹ES6核心語法的文章后再回來。30分鐘掌握ES6/ES2015核心內(nèi)容(上) 、30分鐘掌握ES6/ES2015核心內(nèi)容(下)

      class CutePromise {
       // executor是我們實例化CutePromise時傳入的參數(shù)函數(shù),它接受兩個參數(shù),分別是resolve和reject。
       // resolve和reject我們將會定義在constructor當(dāng)中,供executor在執(zhí)行的時候調(diào)用
       constructor(executor) {
       const resolve = () => {}
       const reject = () => {}
       executor(resolve, reject)
       }
      
       // 為實例提供一個then的方法,接收兩個參數(shù)函數(shù),
       // 第一個參數(shù)函數(shù)必傳,它會在promise已成功(fulfilled)以后被調(diào)用
       // 第二個參數(shù)非必傳,它會在promise已失敗(rejected)以后被調(diào)用
       then(onFulfilled, onRejected) {}
      }

      創(chuàng)建了我們的CutePromise后,我們再來搞清楚一個關(guān)鍵點:Promise 對象的狀態(tài)。

      Promise 對象通過自身的狀態(tài),來控制異步操作。一個Promise 實例具有三種狀態(tài):

      • 異步操作未完成(pending)
      • 異步操作成功(fulfilled)
      • 異步操作失敗(rejected)

      上面三種狀態(tài)里面,fulfilled和rejected合在一起稱為resolved(已定型)。狀態(tài)的切換只有兩條路徑:第一種是從pending=>fulfilled,另一種是從pending=>rejected,狀態(tài)一旦切換就不能再改變。

      現(xiàn)在我們來為CutePromise添加狀態(tài),大概流程就是:

      首先,實例化初始過程中,我們先將狀態(tài)設(shè)為PENDING,然后當(dāng)executor執(zhí)行resolve的時候,將狀態(tài)更改為FULFILLED,當(dāng)executor執(zhí)行reject的時候?qū)顟B(tài)更改為REJECTED。同時更新實例的value。

      constructor(executor) {
       ...
       this.state = 'PENDING';
       ...
       const resolve = (result) => {
        this.state = 'FULFILLED';
        this.value = result;
       }
       const reject = (error) => {
        this.state = 'REJECTED';
        this.value = error;
       }
       ...
      }

      再來看下我們的then函數(shù)。then函數(shù)的兩個參數(shù),onFulfilled表示當(dāng)promise異步操作成功時調(diào)用的函數(shù),onRejected表示當(dāng)promise異步操作失敗時調(diào)用的函數(shù)。假如我們調(diào)用then的時候,promise已經(jīng)執(zhí)行完成了(當(dāng)任務(wù)是個同步任務(wù)時),我們可以直接根據(jù)實例的狀態(tài)來執(zhí)行相應(yīng)的函數(shù)。假如promise的狀態(tài)還是PENDING, 那我們就將onFulfilled和onRejected直接存儲到chained這個變量當(dāng)中,等promise執(zhí)行完再調(diào)用。

      constructor(executor) {
       ...
       this.state = 'PENDING';
       
       // chained用來儲存promise執(zhí)行完成以后,需要被依次調(diào)用的一系列函數(shù)
       this.chained = [];
       const resolve = (result) => {
        this.state = 'FULFILLED';
        this.value = result;
        
        // promise已經(jīng)執(zhí)行成功了,可以依次調(diào)用.then()函數(shù)里的onFulfilled函數(shù)了
        for (const { onFulfilled } of this.chained) {
         onFulfilled(res);
        }
       }
      
       ...
      }
      then(onFulfilled, onRejected) {
       if (this.state === 'FULFILLED') {
       onFulfilled(this.value);
       } else if (this.state === 'REJECTED') {
       onRejected(this.value);
       } else {
       this.$chained.push({ onFulfilled, onRejected });
       }
      }

      這樣我們就完成了一個CutePromise的創(chuàng)建,下面是完整代碼,大家可以復(fù)制代碼到控制臺測試一下:

      class CutePromise {
       constructor(executor) {
       if (typeof executor !== 'function') {
        throw new Error('Executor must be a function');
       }
      
       this.state = 'PENDING';
       this.chained = [];
       const resolve = res => {
        if (this.state !== 'PENDING') {
        return;
        }
      
        this.state = 'FULFILLED';
        this.internalValue = res;
        for (const { onFulfilled } of this.chained) {
        onFulfilled(res);
        }
       };
       const reject = err => {
        if (this.state !== 'PENDING') {
        return;
        }
        this.state = 'REJECTED';
        this.internalValue = err;
        for (const { onRejected } of this.chained) {
        onRejected(err);
        }
       };
      
       try {
        executor(resolve, reject);
       } catch (err) {
        reject(err);
       }
       }
       
       then(onFulfilled, onRejected) {
       if (this.state === 'FULFILLED') {
        onFulfilled(this.internalValue);
       } else if (this.$state === 'REJECTED') {
        onRejected(this.internalValue);
       } else {
        this.chained.push({ onFulfilled, onRejected });
       }
       }
      }

      提供一下測試代碼:

      let p = new CutePromise(resolve => {
       setTimeout(() => resolve('Hello'), 100);
      });
      p.then(res => console.log(res));
      p = new CutePromise((resolve, reject) => {
       setTimeout(() => reject(new Error('woops')), 100);
      });
      p.then(() => {}, err => console.log('Async error:', err.stack));
      p = new CutePromise(() => { throw new Error('woops'); });
      p.then(() => {}, err => console.log('Sync error:', err.stack));

      總結(jié)

      以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對創(chuàng)新互聯(lián)的支持。


      網(wǎng)頁題目:如何從零開始利用js手寫一個Promise庫詳解
      標(biāo)題URL:http://ef60e0e.cn/article/jdsiji.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        靖安县| 五河县| 中宁县| 福州市| 色达县| 冕宁县| 自治县| 乐东| 吐鲁番市| 岢岚县| 方山县| 长丰县| 广东省| 新晃| 长顺县| 阜新市| 黄陵县| 泸州市| 辽宁省| 巴塘县| 成都市| 惠州市| 陕西省| 白水县| 满洲里市| 榆中县| 凉城县| 大方县| 莲花县| 荔波县| 九龙坡区| 安义县| 三门峡市| 新宾| 左云县| 景洪市| 任丘市| 兰坪| 吴川市| 册亨县| 谢通门县|