手寫 Promise 所有方法實現(xiàn)

前言

上次我們手寫了一個promise罩润,相信大家已經(jīng)對 Promise 有了深度的理解热某,這次我們再把 Promise 的所有相關(guān)方法都實現(xiàn)一下计济。

Promise.prototype.catch


Promise.prototype.catch = function(onRejected) {

  return this.then(null, onRejected)

}

catch 方法相對簡單饭入,就是調(diào)用 promise 自身的 then 方法嘹悼,只傳入失敗的回調(diào)叛甫。因為 then 方法本身具有值的傳遞性,所以我們只需傳入失敗的回調(diào)即可杨伙,即使沒有成功的回調(diào)其监,也會將值自動的傳遞下去。

Promise.prototype.finally

無論成功還是失敗都會執(zhí)行 finally


Promise.prototype.finally = function(onFinished) {

  return this.then(val => {

    onFinished()

    return val

  }).catch((err) => {

    onFinished()

    return err

  })

}

finally 需要注意

  1. finally 的回調(diào)沒有參數(shù)

  2. promise 如果成功限匣,則將成功的值正常傳遞下去抖苦,不會因 finally 而斷掉,舉例:

  3. promise 如果失敗,同上


Promise

  .resolve(1)

  .finally(val => console.log(val)) // undefind

  .then(val => console.log(val)) // 1

Promise

  .reject('error')

  .finally(val => console.log(val)) // undefind

  .catch(err => console.log(err)) // error

Promise.resolve

返回一個成功的 promise


Promise.resolve = function(val) {

  return new Promise(resolve => {

    resolve(val)

  })

}

emmm 一眼就懂

image

Promise.reject

返回一個失敗的 promise


Promise.reject = function(val) {

  return new Promise((resolve, reject) => {

    reject(val)

  })

}

啥也不說了锌历。贮庞。。

image

Promise.all

返回一個 promise 實例究西。接受一個可迭代的對象窗慎,會等 iterable 參數(shù)內(nèi)所有的 promise 都 resolved 時被 reslove,如果有一個 rejected卤材,則此實例被 reject遮斥。

如果 iterable 沒有 promise,則此實例直接被 resolve扇丛。

返回值是一個數(shù)組术吗,數(shù)組的值按照 iterable 的迭代順序排列。


Promise.all = function(ps) {

  let resolve

  let reject

  const promise = new Promise((r, j) => {

    resolve = r

    reject = j

  })

  let fufilledCount = 0

  let index = 0;

  const ret = [];

  const wrapFufilled = i => {

    return val => {

      fufilledCount += 1

      ret[i] = val

      if (fufilledCount >= index) {

        resolve(ret)

      }

    } 

  }

  const wrapRejected = i => {

    return err => {

      reject(err)

    }

  }

  for (let p of ps) {

    Promise.resolve(p).then(wrapFufilled(index), wrapRejected(index))

    index += 1

  }

  return promise

}

注意幾個要點

  1. 因為接受的是一個可迭代對象(iterable)帆精,所以我們用 for of 遍歷较屿。

  2. 這里我們用 Promise.resolve() 包裝一下所有的 promise。

  3. wrapFufilled 的目的是為了記錄當前遍歷的 index实幕。

Promise.race

返回一個 promise吝镣,一旦迭代器中的某個promise解決或拒絕,返回的 promise就會解決或拒絕昆庇。


Promise.race = function(ps) {

  let resolve

  let reject

  const promise = new Promise((r, j) => {

    resolve = r

    reject = j

  })

  for (let p of ps) {

    Promise.resolve(p).then(

      val => resolve(val),

      err => reject(err)

    )

  }

  return promise

}

Promise.any

只要其中的一個 promise 成功末贾,就返回那個已經(jīng)成功的 promise 。如果可迭代對象中沒有一個 promise 成功(即所有的 promises 都失敗/拒絕)整吆,就返回一個失敗的 promise 和AggregateError類型的實例拱撵,它是 Error 的一個子類,用于把單一的錯誤集合在一起表蝙。

本質(zhì)上拴测,這個方法和Promise.all()是相反的


Promise.any = function(ps) {

  let resolve

  let reject

  const promise = new Promise((r, j) => {

    resolve = r

    reject = j

  })

  let errCount = 0

  let pCount = 0

  for (let p of ps) {

    pCount += 1

    Promise.resolve(p).then(

      val => resolve(val),

      err => {

        errCount += 1

        if (errCount >= pCount) {

          reject(new AggregateError('All promises were rejected'))

        }

      }

    )

  }

  return promise

}

Promise.allSettled

返回一個在所有給定的promise都已經(jīng)fulfilled或rejected后的promise,并帶有一個對象數(shù)組府蛇,每個對象表示對應(yīng)的promise結(jié)果集索。

這里舉一個例子:


const promise1 = Promise.resolve(3);

const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'));

const promises = [promise1, promise2];

Promise.allSettled(promises).

  then((results) => results.forEach((result) => console.log(result)));



// 輸出結(jié)果

// Object { status: "fulfilled", value: 3 }

// Object { status: "rejected", reason: "foo" }

具體實現(xiàn):


Promise.allSettled = function(ps) {

  let resolve

  let reject

  const promise = new Promise((r, j) => {

    resolve = r

    reject = j

  })

  let finishedCount = 0

  let index = 0;

  const ret = [];

  const wrapFufilled = i => {

    return val => {

      finishedCount += 1

      ret[i] = {

        status: 'fufilled',

        value: val

      }

      if (finishedCount >= index) {

        resolve(ret)

      }

    } 

  }

  const wrapRejected = i => {

    return err => {

      finishedCount += 1

      ret[i] = {

        status: 'rejected',

        value: err

      }

      if (finishedCount >= index) {

        resolve(ret)

      }

    }

  }

  for (let p of ps) {

    Promise.resolve(p).then(wrapFufilled(index), wrapRejected(index))

    index += 1

  }

  return promise

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市汇跨,隨后出現(xiàn)的幾起案子务荆,更是在濱河造成了極大的恐慌,老刑警劉巖穷遂,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件函匕,死亡現(xiàn)場離奇詭異,居然都是意外死亡蚪黑,警方通過查閱死者的電腦和手機盅惜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進店門中剩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人抒寂,你說我怎么就攤上這事结啼。” “怎么了屈芜?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵妆棒,是天一觀的道長。 經(jīng)常有香客問我沸伏,道長糕珊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任毅糟,我火速辦了婚禮红选,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘姆另。我一直安慰自己喇肋,他們只是感情好,可當我...
    茶點故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布迹辐。 她就那樣靜靜地躺著蝶防,像睡著了一般。 火紅的嫁衣襯著肌膚如雪明吩。 梳的紋絲不亂的頭發(fā)上间学,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天,我揣著相機與錄音印荔,去河邊找鬼低葫。 笑死,一個胖子當著我的面吹牛仍律,可吹牛的內(nèi)容都是我干的嘿悬。 我是一名探鬼主播,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼水泉,長吁一口氣:“原來是場噩夢啊……” “哼善涨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起草则,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤钢拧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后畔师,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體娶靡,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡牧牢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年看锉,在試婚紗的時候發(fā)現(xiàn)自己被綠了姿锭。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡伯铣,死狀恐怖呻此,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情腔寡,我是刑警寧澤焚鲜,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站放前,受9級特大地震影響忿磅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜凭语,卻給世界環(huán)境...
    茶點故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一葱她、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧似扔,春花似錦吨些、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至黔寇,卻和暖如春偶器,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背缝裤。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工状囱, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人倘是。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓亭枷,卻偏偏與公主長得像,于是被迫代替她去往敵國和親搀崭。 傳聞我的和親對象是個殘疾皇子叨粘,可洞房花燭夜當晚...
    茶點故事閱讀 43,543評論 2 349