欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript實(shí)現(xiàn)Promise流程詳解

 更新時(shí)間:2022年09月01日 14:51:15   作者:搞前端的小菜  
首先呢,Promise是異步中比較重要的知識點(diǎn),學(xué)習(xí)的最好方法就是掌握它的基本原理。所以這一篇主要說一下如何用JS來實(shí)現(xiàn)一個(gè)自己的promise

構(gòu)造函數(shù)

首先我們來看一下我們是如何使用promise的,我們在實(shí)例化對象是這么使用的:

    let p1 = new Promise((resolve, reject) => {
      let random = Math.floor(Math.random() * 10);
      if (random > 4) {
        resolve('sucess')
      } else {
        reject('erro')
      }
    })

所以我們在創(chuàng)建我們自己的類要考慮到如何使用這個(gè)參數(shù)。

我們來看一下, new Promise 的時(shí)候傳了一個(gè)回調(diào)函數(shù),在這個(gè)回調(diào)函數(shù)中的代碼應(yīng)該是被立即執(zhí)行的。

而在這個(gè)回調(diào)函數(shù)中,還帶有這兩個(gè)參數(shù)resolve和reject(也是回調(diào)函數(shù))。

所以在我們的構(gòu)造函數(shù)中,應(yīng)該是有這兩個(gè)函數(shù)resolve和reject(暫時(shí)先不管這兩個(gè)函數(shù)是做什么的)。

我們知道promise是有三個(gè)屬性的:

pending : 待定

fulfilled : 對應(yīng)resolve函數(shù)

rejected : 對應(yīng)reject函數(shù)

并且狀態(tài)一旦改變就不能再更改了。

所以我們的構(gòu)造函數(shù)之中應(yīng)該有表示當(dāng)前promise狀態(tài)的屬性。

我們知道不管使用resolve還是reject都會傳入一個(gè)res變量,作為結(jié)果值,所以我們在用一個(gè)屬性來保存resolve和reject的結(jié)果值。

最后我們可以設(shè)計(jì)出這樣的構(gòu)造函數(shù):

function Mypromise (config) {
  this.status = 'pending';
  this.res = ''
  let resolve = (data) => {
    this.status = 'fulfilled';
    this.res = data
  }
  let reject = (data) => {
    this.status = 'rejected';
    this.res = data
  }
  config(resolve, reject)
}

then 和 catch方法

我們先來回顧一哈怎么使用這兩個(gè)方法:

    p1
      .then(res => {
        console.log(res);
      })
      .then(res => {
        console.log(res);
      })
      .catch(err => {
        console.log(err);
      })

上面的代碼我們可以看到,then和catch方法,都接受了一個(gè)回調(diào)函數(shù)

而這個(gè)回調(diào)函數(shù)的參數(shù)也就是我們之前定義的this.res。

所以我們可以想到這么做:

Mypromise.prototype.then = function (config) {
  if (this.status == 'fulfilled') {
    config(this.res)
  }
}
Mypromise.prototype.catch = function (config) {
  if (this.status == 'rejected') {
    config(this.res)
  }
}

但是這種方法不能實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用,就是不能連著使用then方法。

但是如果我想實(shí)現(xiàn)出這個(gè)模式,我們應(yīng)該在then方法下回一個(gè)對象,而這個(gè)對象正常來講就是this。

所以我們可以直接返回this嗎,看下面這個(gè)情況。

p1
  .then(res => {
    console.log(res);
    return new Promise((resolve, reject) => {
      resolve('1111')
    })
  })
  .then(res => {
    console.log(res);
  })
  .catch(err => {
    console.log(err);
  })

在then方法下如果返回了一個(gè)新的promise的話,我們就不能直接在then方法里面直接返回this了。

所以我們應(yīng)該先判斷then的回調(diào)函數(shù)是否返回了新的對象,如果沒有才返回當(dāng)前then的this對象。

Mypromise.prototype.then = function (config) {
  if (this.status == 'fulfilled') {
    var res = config(this.res)
  }
  return res || this;
}
Mypromise.prototype.catch = function (config) {
  if (this.status == 'rejected') {
    var res = config(this.res)
  }
  return res || this;
}

解決異步問題

上面的代碼,似乎看著沒有什么問題了,但是如果我這么寫的話:

    let p2 = new Mypromise((resolve, reject) => {
      setTimeout(() => {
        reject('p2 resolve')
      }, 1000);
    })

問題就大大的出來了,為什么呢? 因?yàn)槲以趐2.then的時(shí)候,定時(shí)器沒有跑完,所以p2的狀態(tài)現(xiàn)在還是pending,根本不會走下去。

這里面我們用一種經(jīng)典的解決模式,在我寫之前的axios和路由也經(jīng)??梢钥吹?。

在then方法中,如果當(dāng)前狀態(tài)為pending(這句話很重要o),我們就把當(dāng)前的回調(diào)函數(shù)保存下來(不一定是一個(gè),有可能是多個(gè)then,所以我們采用數(shù)組保存)。

那我們保存起來什么時(shí)候用呢?當(dāng)然是在定時(shí)器結(jié)束后用!那定時(shí)器什么時(shí)候結(jié)束呢?當(dāng)然是當(dāng)前promise狀態(tài)改變的時(shí)候,所以,我們在resolve和reject方法之中,要將這些方法進(jìn)行調(diào)用?。?!

所以我們要修改構(gòu)造函數(shù):

function Mypromise (config) {
  this.status = 'pending';
  this.res = '';
  this.saveResolve = [];
  this.saveReject = [];
  let resolve = (data) => {
    if (this.status == 'pending') {
      this.status = 'fulfilled';
      this.res = data
      this.saveResolve.forEach(val => {
        val(this.res)
      })
    }
  }
  let reject = (data) => {
    if (this.status == 'pending') {
      this.status = 'rejected';
      this.res = data
      this.saveReject.forEach(val => {
        val(this.res)
      })
    }
  }
  config(resolve, reject);
}

然后再修改我們的then和catch方法:

Mypromise.prototype.then = function (config) {
  if (this.status == 'pending') {
    this.saveResolve.push(config);
  }
  if (this.status == 'fulfilled') {
    var res = config(this.res)
  }
  return res || this;
}
Mypromise.prototype.catch = function (config) {
  if (this.status == 'pending') {
    this.saveReject.push(config)
  }
  if (this.status == 'rejected') {
    var res = config(this.res)
  }
  return res || this;
}

這樣關(guān)于異步的問題我們就解決了。

all和race方法

還是老樣子,在寫之前我們先回顧一下是怎么用的:

    Mypromise.all([p2, p3, p4])
      .then(res => {
        console.log(res);
      })
      .catch(err => {
        console.log(err);
      })
    Mypromise.race([p2, p3, p4])
      .then(res => {
        console.log(res);
      })
      .catch(err => {
        console.log(err);
      })

那我們知道,二者都死以一個(gè)數(shù)組作為參數(shù),這里面我門就不考慮其他的情況了,我就當(dāng)數(shù)組里面全是promise對象了。。。

二者的區(qū)別在于:

all:當(dāng)所有的promise都執(zhí)行完,并且狀態(tài)都為fulfilled,all方法返回的promise為fulfilled,否則為rejected。

race:第一個(gè)出現(xiàn)結(jié)果的promise對象就是race放回的promise的結(jié)果。

現(xiàn)在我們來想一下all方法如何來實(shí)現(xiàn),我們拿到了數(shù)組參數(shù)之后,一定是要遍歷一遍的。

然后對于每一個(gè)元素都調(diào)用then方法和catch方法。

then方法要有一個(gè)結(jié)果數(shù)組保存每個(gè)promise的結(jié)果值。

我們可以用一個(gè)計(jì)數(shù)器來計(jì)算then方法的調(diào)用次數(shù),如果計(jì)數(shù)器的大小等于數(shù)組長度,那么就證明所有的promise全部都是fulfilled,可以返回結(jié)果數(shù)組。

catch方法只要是被調(diào)用了一次,那么直接返回結(jié)果,不多bb,直接返回

最后記住要把新的promise返回o。

Mypromise.all = function (arr) {
  let result = [];
  let count = 0;
  let promise = new Mypromise((resolve, reject) => {
    for (var i = 0; i < arr.length; i++) {
      arr[i]
        .then(res => {
          result.push(res);
          count++;
          if (count == arr.length) resolve(result);
        })
        .catch(err => {
          reject(err)
        })
    }
  })
  return promise
}

race的方法的話,實(shí)現(xiàn)起來可能就更簡單了,不管那個(gè)promise的then方法還是catch方法觸發(fā)了,直接返回結(jié)果:

Mypromise.race = function (arr) {
  let promise = new Mypromise((resolve, reject) => {
    for (var i = 0; i < arr.length; i++) {
      arr[i]
        .then(res => {
          resolve(res);
        })
        .catch(err => {
          reject(err)
        })
    }
  })
  return promise
}

到此這篇關(guān)于JavaScript實(shí)現(xiàn)Promise流程詳解的文章就介紹到這了,更多相關(guān)JS Promise內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JavaScript  cookie 跨域訪問之廣告推廣

    JavaScript cookie 跨域訪問之廣告推廣

    這篇文章主要介紹了JavaScript cookie 跨域訪問之廣告推廣 的相關(guān)資料,需要的朋友可以參考下
    2016-04-04
  • Bootstrap Chart組件使用教程

    Bootstrap Chart組件使用教程

    圖表組件Chart.js是Bootstrap比較好用的組件之一,與一款收費(fèi)的組件highchart類似,效果上來看免費(fèi)與收費(fèi)的產(chǎn)品相差還是有一點(diǎn)點(diǎn)的,不過功能上差不多能滿足我們項(xiàng)目的需要,本文給大家介紹Bootstrap Chart組件使用,需要的朋友參考下吧
    2016-04-04
  • 微信小程序父子組件通信詳細(xì)介紹

    微信小程序父子組件通信詳細(xì)介紹

    這篇文章主要介紹了小程序中父子組件通信詳解,在父組件中,為子組件添加屬性數(shù)據(jù),即可實(shí)現(xiàn)父組件向子組件通信,文章通過圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-11-11
  • Ant Design Blazor 組件庫的路由復(fù)用多標(biāo)簽頁功能

    Ant Design Blazor 組件庫的路由復(fù)用多標(biāo)簽頁功能

    在 Ant Design Blazor 組件庫中實(shí)現(xiàn)多標(biāo)簽頁組件的呼聲日益高漲。于是,我利用周末時(shí)間,結(jié)合 Blazor 內(nèi)置路由組件實(shí)現(xiàn)了基于 Tabs 組件的 ReuseTabs 組件,需要的朋友跟隨小編一起看看吧
    2021-07-07
  • javascript實(shí)現(xiàn)顯示和隱藏div方法匯總

    javascript實(shí)現(xiàn)顯示和隱藏div方法匯總

    本文章通過幾個(gè)簡單的實(shí)例告訴你如何來實(shí)例關(guān)于隱藏與顯示div層及關(guān)閉層與隱藏的區(qū)別分析哦,有需要的同學(xué)可以參考一下本文章。
    2015-08-08
  • JavaScript資源預(yù)加載組件和滑屏組件的使用推薦

    JavaScript資源預(yù)加載組件和滑屏組件的使用推薦

    這篇文章主要介紹了JavaScript資源預(yù)加載組件和滑屏組件的使用推薦,分別為preload和slide的用法講解,使用起來非常簡單,需要的朋友可以參考下
    2016-03-03
  • js簡單工廠模式用法實(shí)例

    js簡單工廠模式用法實(shí)例

    這篇文章主要介紹了js簡單工廠模式用法,實(shí)例分析了javascript工廠模式的實(shí)現(xiàn)原理,需要的朋友可以參考下
    2015-06-06
  • 詳解JavaScript的三種this指向方法

    詳解JavaScript的三種this指向方法

    這篇文章主要介紹JavaScript的三種this指向的方法:call()、bind()、apply(),文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2023-05-05
  • JavaScript實(shí)現(xiàn)限時(shí)秒殺功能

    JavaScript實(shí)現(xiàn)限時(shí)秒殺功能

    各種電商活動都喜換選擇限時(shí)秒殺活動形式,這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)限時(shí)秒殺功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • javascript文本模板用法實(shí)例

    javascript文本模板用法實(shí)例

    這篇文章主要介紹了javascript文本模板用法,實(shí)例分析了文本模板的相關(guān)實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-07-07

最新評論