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

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

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

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

首先我們來(lái)看一下我們是如何使用promise的,我們?cè)趯?shí)例化對(duì)象是這么使用的:

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

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

我們來(lái)看一下, 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 : 對(duì)應(yīng)resolve函數(shù)

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

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

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

我們知道不管使用resolve還是reject都會(huì)傳入一個(gè)res變量,作為結(jié)果值,所以我們?cè)谟靡粋€(gè)屬性來(lái)保存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方法

我們先來(lái)回顧一哈怎么使用這兩個(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è)對(duì)象,而這個(gè)對(duì)象正常來(lái)講就是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ù)是否返回了新的對(duì)象,如果沒(méi)有才返回當(dāng)前then的this對(duì)象。

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;
}

解決異步問(wèn)題

上面的代碼,似乎看著沒(méi)有什么問(wèn)題了,但是如果我這么寫(xiě)的話:

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

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

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

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

那我們保存起來(lái)什么時(shí)候用呢?當(dāng)然是在定時(shí)器結(jié)束后用!那定時(shí)器什么時(shí)候結(jié)束呢?當(dāng)然是當(dāng)前promise狀態(tài)改變的時(shí)候,所以,我們?cè)趓esolve和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)于異步的問(wèn)題我們就解決了。

all和race方法

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

    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ù),這里面我門(mén)就不考慮其他的情況了,我就當(dāng)數(shù)組里面全是promise對(duì)象了。。。

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

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

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

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

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

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

我們可以用一個(gè)計(jì)數(shù)器來(lái)計(jì)算then方法的調(diào)用次數(shù),如果計(jì)數(shù)器的大小等于數(shù)組長(zhǎng)度,那么就證明所有的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)起來(lái)可能就更簡(jiǎ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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

曲麻莱县| 沙湾县| 曲沃县| 特克斯县| 司法| 鄂托克旗| 闽清县| 西平县| 大庆市| 凌云县| 阿勒泰市| 阳春市| 安国市| 疏勒县| 明溪县| 桐梓县| 衡东县| 赫章县| 南投市| 临沭县| 云林县| 前郭尔| 涿鹿县| 葵青区| 澄江县| 时尚| 中超| 漯河市| 应城市| 石台县| 南江县| 汪清县| 吴江市| 武强县| 淳安县| 当涂县| 武威市| 白银市| 黔江区| 涞水县| 万盛区|