最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

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

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

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

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

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

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

我們知道promise是有三個屬性的:

pending : 待定

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

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

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

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

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

最后我們可以設(shè)計出這樣的構(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方法

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

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

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

而這個回調(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)
  }
}

但是這種方法不能實現(xiàn)鏈式調(diào)用,就是不能連著使用then方法。

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

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

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

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

所以我們應(yīng)該先判斷then的回調(diào)函數(shù)是否返回了新的對象,如果沒有才返回當前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);
    })

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

這里面我們用一種經(jīng)典的解決模式,在我寫之前的axios和路由也經(jīng)常可以看到。

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

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

所以我們要修改構(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);
      })

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

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

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

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

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

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

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

我們可以用一個計數(shù)器來計算then方法的調(diào)用次數(shù),如果計數(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的方法的話,實現(xiàn)起來可能就更簡單了,不管那個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實現(xiàn)Promise流程詳解的文章就介紹到這了,更多相關(guān)JS Promise內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

镇坪县| 澜沧| 峨边| 阿巴嘎旗| 阿图什市| 吉水县| 武安市| 平度市| 宕昌县| 台江县| 华容县| 梨树县| 铜山县| 西城区| 弥渡县| 固原市| 泰顺县| 新化县| 英德市| 天长市| 抚松县| 灵丘县| 蒙城县| 固阳县| 邹平县| 富宁县| 文成县| 花莲县| 蚌埠市| 时尚| 迁西县| 驻马店市| 禹州市| 光泽县| 灵武市| 锦州市| 白玉县| 广州市| 汉中市| 阳江市| 马龙县|