<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          手寫(xiě) Promise 全部 API 教程

          共 37383字,需瀏覽 75分鐘

           ·

          2022-02-27 05:49


          前言

          我們?cè)?上篇文章?用了很大功夫?qū)崿F(xiàn)了 Promise 的核心方法,并且通過(guò)了 Promises/A+ 官方872個(gè)測(cè)試用例測(cè)試,接下來(lái)實(shí)現(xiàn)這些靜態(tài)方法已經(jīng)是小菜一碟了,因?yàn)檫@些 API 全部是對(duì)前面的封裝而已。

          上篇文章在這里:手把手一行一行代碼教你 "手寫(xiě) Promise",完美通過(guò) Promises/A+ 官方872個(gè)測(cè)試用例

          官方 Promise 還有很多API?,除了 then 方法以外還有?兩個(gè)實(shí)例方法:

          • Promise.prototype.catch

          • Promise.prototype.finally

          ? 以及目前 Promise 規(guī)范的?六個(gè)靜態(tài)方法

          • Promise.resolve

          • Promise.reject

          • Promise.all

          • Promise.allSettled

          • Promise.any

          • Promise.race

          雖然這些都不在 Promise/A+ 規(guī)范里面,但是我們也來(lái)實(shí)現(xiàn)一下吧,加深理解。其實(shí)我們前面我們用了很大功夫?qū)崿F(xiàn)了 Promise/A+ ,現(xiàn)在再來(lái)實(shí)現(xiàn)這些已經(jīng)是小菜一碟了,因?yàn)檫@些API全部是前面的封裝而已。

          1. 實(shí)現(xiàn) Promise.resolve

          Promise.resolve(value)?將給定的一個(gè)值轉(zhuǎn)為Promise對(duì)象。

          • 如果這個(gè)值是一個(gè) promise ,那么將返回這個(gè) promise ;

          • 如果這個(gè)值是thenable(即帶有"then"?方法),返回的promise會(huì)“跟隨”這個(gè)thenable的對(duì)象,采用它的最終狀態(tài);

          • 否則返回的promise將以此值完成,即以此值執(zhí)行resolve()方法 (狀態(tài)為fulfilled)。

          根據(jù)規(guī)范我們這樣實(shí)現(xiàn)(寫(xiě)法一):

          class myPromise {
          ...
          }

          function resolvePromise(promise2, x, resolve, reject) {
          ...
          }

          /**
          * Promise.resolve()
          * @param {[type]} value 要解析為 Promise 對(duì)象的值
          */

          + myPromise.resolve = function (value) {
          + // 如果這個(gè)值是一個(gè) promise ,那么將返回這個(gè) promise
          + if (value instanceof myPromise) {
          + return value;
          + } else if (value instanceof Object && 'then' in value) {
          + // 如果這個(gè)值是thenable(即帶有`"then" `方法),返回的promise會(huì)“跟隨”這個(gè)thenable的對(duì)象,采用它的最終狀態(tài);
          + return new myPromise((resolve, reject) => {
          + value.then(resolve, reject);
          + })
          + }
          +
          + // 否則返回的promise將以此值完成,即以此值執(zhí)行`resolve()`方法 (狀態(tài)為fulfilled)
          + return new myPromise((resolve) => {
          + resolve(value)
          + })
          + }

          module.exports = myPromise;

          使用官方例子測(cè)試一下:

          const myPromise = require('./promiseOtherAPI');

          const promise1 = myPromise.resolve(123);

          promise1.then((value) => {
          console.log(value);
          // expected output: 123
          });

          // Resolve一個(gè)thenable對(duì)象
          var p1 = myPromise.resolve({
          then: function (onFulfill) {
          onFulfill("Resolving");
          }
          });
          console.log(p1 instanceof myPromise) // true, 這是一個(gè)Promise對(duì)象

          setTimeout(() => {
          console.log('p1 :>> ', p1);
          }, 1000);

          p1.then(function (v) {
          console.log(v); // 輸出"fulfilled!"
          }, function (e) {
          // 不會(huì)被調(diào)用
          });

          // Thenable在callback之前拋出異常
          // myPromise rejects
          var thenable = {
          then: function (resolve) {
          throw new TypeError("Throwing");
          resolve("Resolving");
          }
          };

          var p2 = myPromise.resolve(thenable);
          p2.then(function (v) {
          // 不會(huì)被調(diào)用
          }, function (e) {
          console.log(e); // TypeError: Throwing
          });

          輸出結(jié)果:

          true
          123
          Resolving
          TypeError: Throwing
          p1 :>> myPromise {PromiseState: 'fulfilled', PromiseResult: 'Resolving', onFulfilledCallbacks: Array(1), onRejectedCallbacks: Array(1)}

          測(cè)試通過(guò) ?

          靜態(tài)方法改造

          類(lèi)(class)通過(guò) static 關(guān)鍵字定義靜態(tài)方法。不能在類(lèi)的實(shí)例上調(diào)用靜態(tài)方法,而應(yīng)該通過(guò)類(lèi)本身調(diào)用。這些通常是實(shí)用程序方法,例如創(chuàng)建或克隆對(duì)象的功能。

          類(lèi)相當(dāng)于實(shí)例的原型,所有在類(lèi)中定義的方法,都會(huì)被實(shí)例繼承。如果在一個(gè)方法前,加上static關(guān)鍵字,就表示該方法不會(huì)被實(shí)例繼承,而是直接通過(guò)類(lèi)來(lái)調(diào)用,這就稱(chēng)為“靜態(tài)方法”。

          寫(xiě)法二、使用靜態(tài)方法 static:

          class myPromise {
          ...

          resolve(result) {
          ...
          }

          reject(reason) {
          ...
          }

          then(onFulfilled, onRejected) {
          ...
          }

          /**
          * Promise.resolve()
          * @param {[type]} value 要解析為 Promise 對(duì)象的值
          */

          + static resolve(value) {
          + // 如果這個(gè)值是一個(gè) promise ,那么將返回這個(gè) promise
          + if (value instanceof myPromise) {
          + return value;
          + } else if (value instanceof Object && 'then' in value) {
          + // 如果這個(gè)值是thenable(即帶有`"then" `方法),返回的promise會(huì)“跟隨”這個(gè)thenable的對(duì)象,采用它的最終狀態(tài);
          + return new myPromise((resolve, reject) => {
          + value.then(resolve, reject);
          + })
          + }
          +
          + // 否則返回的promise將以此值完成,即以此值執(zhí)行`resolve()`方法 (狀態(tài)為fulfilled)
          + return new myPromise((resolve) => {
          + resolve(value)
          + })
          + }
          }

          function resolvePromise(promise2, x, resolve, reject) {
          ...
          }

          module.exports = myPromise;

          2. 實(shí)現(xiàn) Promise.reject

          Promise.reject()方法返回一個(gè)帶有拒絕原因的Promise對(duì)象。

          官方例子:

          Promise.reject(new Error('fail')).then(function() {
          // not called
          }, function(error) {
          console.error(error); // Stacktrace
          });

          輸出結(jié)果:

          根據(jù)規(guī)范我們這樣實(shí)現(xiàn)(寫(xiě)法一):

          class myPromise {
          ...
          }

          function resolvePromise(promise2, x, resolve, reject) {
          ...
          }

          myPromise.resolve = function (value) {
          ...
          }

          /**
          * myPromise.reject
          * @param {*} reason 表示Promise被拒絕的原因
          * @returns
          */

          + myPromise.reject = function (reason) {
          + return new myPromise((resolve, reject) => {
          + reject(reason);
          + })
          + }

          module.exports = myPromise;

          使用官方用例測(cè)試一下:

          const myPromise = require('./promiseOtherAPI')

          myPromise.reject(new Error('fail')).then(function () {
          // not called
          }, function (error) {
          console.error(error); // Error: fail
          });

          輸出結(jié)果:

          Error: fail

          測(cè)試通過(guò) ?

          寫(xiě)法二、使用靜態(tài)方法 static:

          class myPromise {
          ...

          resolve(result) {
          ...
          }

          reject(reason) {
          ...
          }

          then(onFulfilled, onRejected) {
          ...
          }

          /**
          * Promise.resolve()
          * @param {[type]} value 要解析為 Promise 對(duì)象的值
          */

          static resolve(value) {
          // 如果這個(gè)值是一個(gè) promise ,那么將返回這個(gè) promise
          if (value instanceof myPromise) {
          return value;
          } else if (value instanceof Object && 'then' in value) {
          // 如果這個(gè)值是thenable(即帶有`"then" `方法),返回的promise會(huì)“跟隨”這個(gè)thenable的對(duì)象,采用它的最終狀態(tài);
          return new myPromise((resolve, reject) => {
          value.then(resolve, reject);
          })
          }

          // 否則返回的promise將以此值完成,即以此值執(zhí)行`resolve()`方法 (狀態(tài)為fulfilled)
          return new myPromise((resolve) => {
          resolve(value)
          })
          }

          /**
          * myPromise.reject
          * @param {*} reason 表示Promise被拒絕的原因
          * @returns
          */

          + static reject(reason) {
          + return new myPromise((resolve, reject) => {
          + reject(reason);
          + })
          + }
          }

          function resolvePromise(promise2, x, resolve, reject) {
          ...
          }

          module.exports = myPromise;

          3. 實(shí)現(xiàn) Promise.prototype.catch

          catch()?方法返回一個(gè)Promise,并且處理拒絕的情況。它的行為與調(diào)用Promise.prototype.then(undefined, onRejected)?相同。

          事實(shí)上, calling?obj.catch(onRejected)?內(nèi)部calls?obj.then(undefined, onRejected)。(這句話的意思是,我們顯式使用obj.catch(onRejected),內(nèi)部實(shí)際調(diào)用的是obj.then(undefined, onRejected))

          Promise.prototype.catch()方法是.then(null, rejection).then(undefined, rejection)的別名,用于指定發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù)。

          因此我們可以這樣來(lái)實(shí)現(xiàn):

          class myPromise {
          ...

          then(onFulfilled, onRejected) {
          ...
          }

          + catch (onRejected) {
          + return this.then(undefined, onRejected)
          + }
          }

          function resolvePromise(promise2, x, resolve, reject) {
          ...
          }

          module.exports = myPromise;

          就一行代碼,我的天,居然這么簡(jiǎn)單??

          我們用官方例子來(lái)測(cè)試一下吧

          const myPromise = require('./promiseOtherAPI')

          var p1 = new myPromise(function (resolve, reject) {
          resolve('Success');
          });

          p1.then(function (value) {
          console.log(value); // "Success!"
          throw 'oh, no!';
          }).catch(function (e) {
          console.log(e); // "oh, no!"
          }).then(function () {
          console.log('after a catch the chain is restored');
          }, function () {
          console.log('Not fired due to the catch');
          });

          // 以下行為與上述相同
          p1.then(function (value) {
          console.log(value); // "Success!"
          return Promise.reject('oh, no!');
          }).catch(function (e) {
          console.log(e); // "oh, no!"
          }).then(function () {
          console.log('after a catch the chain is restored');
          }, function () {
          console.log('Not fired due to the catch');
          });

          // 捕獲異常
          const p2 = new myPromise(function (resolve, reject) {
          throw new Error('test');
          });
          p2.catch(function (error) {
          console.log(error);
          });
          // Error: test

          輸出:

          Success
          Success
          Error: test
          oh, no!
          oh, no!
          after a catch the chain is restored
          after a catch the chain is restored

          測(cè)試通過(guò),沒(méi)毛病??

          4. 實(shí)現(xiàn) Promise.prototype.finally

          finally()?方法返回一個(gè)Promise。在promise結(jié)束時(shí),無(wú)論結(jié)果是fulfilled或者是rejected,都會(huì)執(zhí)行指定的回調(diào)函數(shù)。這為在Promise是否成功完成后都需要執(zhí)行的代碼提供了一種方式。

          這避免了同樣的語(yǔ)句需要在then()catch()中各寫(xiě)一次的情況。該方法是 ES2018 引入標(biāo)準(zhǔn)的。

          由于無(wú)法知道promise的最終狀態(tài),所以finally的回調(diào)函數(shù)中不接收任何參數(shù),它僅用于無(wú)論最終結(jié)果如何都要執(zhí)行的情況。

          根據(jù)規(guī)范我們這樣實(shí)現(xiàn):

          class myPromise {
          ...
          catch (onRejected) {
          return this.then(undefined, onRejected)
          }

          /**
          * finally
          * @param {*} callBack 無(wú)論結(jié)果是fulfilled或者是rejected,都會(huì)執(zhí)行的回調(diào)函數(shù)
          * @returns
          */

          + finally(callBack) {
          + return this.then(callBack, callBack)
          + }
          }

          function resolvePromise(promise2, x, resolve, reject) {
          ...
          }

          myPromise.resolve = function (value) {
          ...
          }

          myPromise.reject = function (reason) {
          ...
          }

          module.exports = myPromise;

          對(duì),就這么簡(jiǎn)單 ?

          測(cè)試一下:

          const myPromise = require('./promiseOtherAPI')

          let p1 = new Promise(function (resolve, reject) {
          resolve(1)
          }).then(function (value) {
          console.log(value);
          }).catch(function (e) {
          console.log(e);
          }).finally(function () {
          console.log('finally');
          });

          輸出結(jié)果:

          1
          finally

          測(cè)試通過(guò) ??????

          5. 實(shí)現(xiàn) Promise.all

          Promise.all()?方法接收一個(gè)promiseiterable類(lèi)型(注:Array,Map,Set都屬于ES6的iterable類(lèi)型)的輸入,并且只返回一個(gè)Promise實(shí)例, 輸入的所有promiseresolve回調(diào)的結(jié)果是一個(gè)數(shù)組。

          返回的這個(gè)Promise的resolve回調(diào)執(zhí)行是在所有輸入的promise的resolve回調(diào)都結(jié)束,或者輸入的iterable里沒(méi)有promise了的時(shí)候。它的reject回調(diào)執(zhí)行是,只要任何一個(gè)輸入的promise的reject回調(diào)執(zhí)行或者輸入不合法的promise就會(huì)立即拋出錯(cuò)誤,并且reject的是第一個(gè)拋出的錯(cuò)誤信息。

          • Promise.all?等待所有都完成(或第一個(gè)失?。?/p>

          • 如果傳入的參數(shù)是一個(gè)空的可迭代對(duì)象,則返回一個(gè)已完成(already resolved)狀態(tài)的 Promise

          • 如果參數(shù)中包含非 promise 值,這些值將被忽略,但仍然會(huì)被放在返回?cái)?shù)組中,如果 promise 完成的話?(也就是如果參數(shù)里的某值不是Promise,則需要原樣返回在數(shù)組里)

          • 在任何情況下,Promise.all 返回的 promise 的完成狀態(tài)的結(jié)果都是一個(gè)數(shù)組,它包含所有的傳入迭代參數(shù)對(duì)象的值(也包括非 promise 值)。

          • 如果傳入的 promise 中有一個(gè)失?。╮ejected),Promise.all 異步地將失敗的那個(gè)結(jié)果給失敗狀態(tài)的回調(diào)函數(shù),而不管其它 promise 是否完成

          根據(jù)規(guī)范我們這樣實(shí)現(xiàn):

          class myPromise {
          ...

          resolve(result) {
          ...
          }
          reject(reason) {
          ...
          }
          then(onFulfilled, onRejected) {
          ...
          }
          static resolve(value) {
          ...
          }
          static reject(reason) {
          ...
          }
          catch (onRejected) {
          ...
          }
          finally(callBack) {
          ...
          }

          /**
          * Promise.all
          * @param {iterable} promises 一個(gè)promise的iterable類(lèi)型(注:Array,Map,Set都屬于ES6的iterable類(lèi)型)的輸入
          * @returns
          */

          + static all(promises) {
          + return new myPromise((resolve, reject) => {
          + // 參數(shù)校驗(yàn)
          + if (Array.isArray(promises)) {
          + let result = []; // 存儲(chǔ)結(jié)果
          + let count = 0; // 計(jì)數(shù)器
          +
          + // 如果傳入的參數(shù)是一個(gè)空的可迭代對(duì)象,則返回一個(gè)已完成(already resolved)狀態(tài)的 Promise
          + if (promises.length === 0) {
          + return resolve(promises);
          + }
          +
          + promises.forEach((item, index) => {
          + // 判斷參數(shù)是否為promise
          + if (item instanceof myPromise) {
          + myPromise.resolve(item).then(
          + value => {
          + count++;
          + // 每個(gè)promise執(zhí)行的結(jié)果存儲(chǔ)在result中
          + result[index] = value;
          + // Promise.all 等待所有都完成(或第一個(gè)失?。?/span>
          + count === promises.length && resolve(result);
          + },
          + reason => {
          + /**
          + * 如果傳入的 promise 中有一個(gè)失?。╮ejected),
          + * Promise.all 異步地將失敗的那個(gè)結(jié)果給失敗狀態(tài)的回調(diào)函數(shù),而不管其它 promise 是否完成
          + */

          + reject(reason);
          + }
          + )
          + } else {
          + // 參數(shù)里中非Promise值,原樣返回在數(shù)組里
          + count++;
          + result[index] = item;
          + count === promises.length && resolve(result);
          + }
          + })
          + } else {
          + return reject(new TypeError('Argument is not iterable'))
          + }
          + })
          + }
          }

          function resolvePromise(promise2, x, resolve, reject) {
          ...
          }

          module.exports = myPromise;

          使用官方例子測(cè)試一下:

          const myPromise = require('../promiseOtherAPI');

          const promise1 = myPromise.resolve(3);
          const promise2 = 42;
          const promise3 = new myPromise((resolve, reject) => {
          setTimeout(resolve, 100, 'foo');
          });

          myPromise.all([promise1, promise2, promise3]).then((values) => {
          console.log(values);
          });
          // expected output: Array [3, 42, "foo"]

          輸出結(jié)果:

          (3) [3, 42, 'foo']

          測(cè)試通過(guò) ??????

          測(cè)試 Promise.all 的快速返回失敗行為

          Promise.all 在任意一個(gè)傳入的 promise 失敗時(shí)返回失敗。例如,如果你傳入的 promise中,有四個(gè) promise 在一定的時(shí)間之后調(diào)用成功函數(shù),有一個(gè)立即調(diào)用失敗函數(shù),那么 Promise.all 將立即變?yōu)槭 ?/p>

          const myPromise = require('../promiseOtherAPI');

          var p1 = new Promise((resolve, reject) => {
          setTimeout(resolve, 1000, 'one');
          });
          var p2 = new Promise((resolve, reject) => {
          setTimeout(resolve, 2000, 'two');
          });
          var p3 = new Promise((resolve, reject) => {
          setTimeout(resolve, 3000, 'three');
          });
          var p4 = new Promise((resolve, reject) => {
          setTimeout(resolve, 4000, 'four');
          });
          var p5 = new Promise((resolve, reject) => {
          reject('reject');
          });

          Promise.all([p1, p2, p3, p4, p5]).then(values => {
          console.log(values);
          }, reason => {
          console.log(reason)
          });

          //From console:
          //"reject"

          輸出結(jié)果:

          測(cè)試通過(guò) ??????

          6. 實(shí)現(xiàn) Promise.allSettled

          Promise.allSettled(iterable)方法返回一個(gè)在所有給定的promise都已經(jīng)fulfilled或rejected后的promise,并帶有一個(gè)對(duì)象數(shù)組,每個(gè)對(duì)象表示對(duì)應(yīng)的promise結(jié)果。

          • 當(dāng)你有多個(gè)彼此不依賴(lài)的異步任務(wù)成功完成時(shí),或者你總是想知道每個(gè)promise的結(jié)果時(shí),通常使用它。

          • 相比之下,Promise.all() 更適合彼此相互依賴(lài)或者在其中任何一個(gè)reject時(shí)立即結(jié)束。

          參數(shù) iterable 是一個(gè)可迭代的對(duì)象,例如Array,其中每個(gè)成員都是Promise。

          對(duì)于每個(gè)結(jié)果對(duì)象,都有一個(gè) status 字符串。如果它的值為 fulfilled,則結(jié)果對(duì)象上存在一個(gè) value 。如果值為 rejected,則存在一個(gè) reason 。value(或 reason )反映了每個(gè) promise 決議(或拒絕)的值。

          在實(shí)現(xiàn)前我們需要驗(yàn)證一點(diǎn),輸入的非promise值應(yīng)該怎么處理?

          為此我們?cè)?Promise.allSettled(iterable)?的參數(shù) iterable 中傳入一個(gè)非promise值,看一下 Promise.allSettled() 方法內(nèi)部會(huì)怎么處理:

          const promise1 = Promise.resolve(3);
          const promise2 = 1;
          const promises = [promise1, promise2];

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

          輸出結(jié)果:

          {status: 'fulfilled', value: 3}
          {status: 'fulfilled', value: 1}

          我們發(fā)現(xiàn) Promise.allSettled() 方法內(nèi)部將非 Promise 值轉(zhuǎn)換成 Promise 了

          那下面我們就將非 Promise 值通過(guò) Promise.resolve 轉(zhuǎn)換為 Promise 進(jìn)行統(tǒng)一處理

          根據(jù)規(guī)范我們這樣實(shí)現(xiàn):

          class myPromise {
          ...

          resolve(result) {
          ...
          }

          reject(reason) {
          ...
          }

          then(onFulfilled, onRejected) {
          ...
          }

          static resolve(value) {
          ...
          }

          static reject(reason) {
          ...
          }

          catch (onRejected) {
          ...
          }

          finally(callBack) {
          ...
          }

          static all(promises) {
          ...
          }

          /**
          * Promise.allSettled
          * @param {*} promises 一個(gè)promise的iterable類(lèi)型(注:Array,Map,Set都屬于ES6的iterable類(lèi)型)的輸入
          * @returns
          */

          + static allSettled(promises) {
          + return new myPromise((resolve, reject) => {
          + // 參數(shù)校驗(yàn)
          + if (Array.isArray(promises)) {
          + let result = []; // 存儲(chǔ)結(jié)果
          + let count = 0; // 計(jì)數(shù)器
          +
          + // 如果傳入的是一個(gè)空數(shù)組,那么就直接返回一個(gè)resolved的空數(shù)組promise對(duì)象
          + if (promises.length === 0) return resolve(promises);
          +
          + promises.forEach((item, index) => {
          + // 非promise值,通過(guò)Promise.resolve轉(zhuǎn)換為promise進(jìn)行統(tǒng)一處理
          + myPromise.resolve(item).then(
          + value => {
          + count++;
          + // 對(duì)于每個(gè)結(jié)果對(duì)象,都有一個(gè) status 字符串。如果它的值為 fulfilled,則結(jié)果對(duì)象上存在一個(gè) value 。
          + result[index] = {
          + status: 'fulfilled',
          + value
          + }
          + // 所有給定的promise都已經(jīng)fulfilled或rejected后,返回這個(gè)promise
          + count === promises.length && resolve(result);
          + },
          + reason => {
          + count++;
          + /**
          + * 對(duì)于每個(gè)結(jié)果對(duì)象,都有一個(gè) status 字符串。如果值為 rejected,則存在一個(gè) reason 。
          + * value(或 reason )反映了每個(gè) promise 決議(或拒絕)的值。
          + */

          + result[index] = {
          + status: 'rejected',
          + reason
          + }
          + // 所有給定的promise都已經(jīng)fulfilled或rejected后,返回這個(gè)promise
          + count === promises.length && resolve(result);
          + }
          + )
          + })
          + } else {
          + return reject(new TypeError('Argument is not iterable'))
          + }
          + })
          + }
          }

          function resolvePromise(promise2, x, resolve, reject) {
          ...
          }

          module.exports = myPromise;

          使用官方例子測(cè)試一下:

          const myPromise = require('../promiseOtherAPI');

          const promise1 = myPromise.resolve(3);
          const promise2 = 1;
          const promises = [promise1, promise2];

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

          setTimeout(() => {
          const p1 = myPromise.resolve(3);
          const p2 = new myPromise((resolve, reject) => setTimeout(reject, 100, 'foo'));
          const ps = [p1, p2];

          myPromise.allSettled(ps).
          then((results) => results.forEach((result) => console.log(result)));
          }, 1000);

          myPromise.allSettled([]).then((results) => console.log(results))

          輸出結(jié)果:

          (0) []
          {status: 'fulfilled', value: 3}
          {status: 'fulfilled', value: 1}
          {status: 'fulfilled', value: 3}
          {status: 'rejected', reason: 'foo'}

          測(cè)試通過(guò) perfect ???

          7. 實(shí)現(xiàn) Promise.any

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

          Promise.any()?接收一個(gè)Promise可迭代對(duì)象,只要其中的一個(gè) promise 成功,就返回那個(gè)已經(jīng)成功的 promise 。

          如果可迭代對(duì)象中沒(méi)有一個(gè) promise 成功(即所有的 promises 都失敗/拒絕),就返回一個(gè)失敗的 promise 和AggregateError類(lèi)型的實(shí)例,它是 Error 的一個(gè)子類(lèi),用于把單一的錯(cuò)誤集合在一起。

          • 如果傳入的參數(shù)是一個(gè)空的可迭代對(duì)象,則返回一個(gè) 已失?。╝lready rejected) 狀態(tài)的 Promise。

          • 如果傳入的參數(shù)不包含任何 promise,則返回一個(gè) 異步完成 (asynchronously resolved)的 Promise。(即將非Promise值,轉(zhuǎn)換為Promise并當(dāng)做成功)

          • 只要傳入的迭代對(duì)象中的任何一個(gè) promise 變成成功(resolve)狀態(tài),或者其中的所有的 promises 都失敗,那么返回的 promise 就會(huì) 異步地(當(dāng)調(diào)用棧為空時(shí)) 變成成功/失?。╮esolved/reject)狀態(tài)。(如果所有Promise都失敗,則報(bào)錯(cuò))

          注意!Promise.any() 方法依然是實(shí)驗(yàn)性的,尚未被所有的瀏覽器完全支持。它當(dāng)前處于 TC39 第四階段草案(Stage 4)

          在?node v14.15.4?版本下測(cè)試?Promise.any()?發(fā)現(xiàn)還沒(méi)有被支持:

          Uncaught TypeError: Promise.any is not a function

          既然是處于草案階段的實(shí)驗(yàn)性 API ,如果想要在各版本瀏覽器中兼容性使用,那實(shí)現(xiàn)?Promise.any()?就很有必要 ??

          根據(jù)規(guī)范我們這樣實(shí)現(xiàn):

          class myPromise {
          ...

          resolve(result) {
          ...
          }

          reject(reason) {
          ...
          }

          then(onFulfilled, onRejected) {
          ...
          }

          static resolve(value) {
          ...
          }

          static reject(reason) {
          ...
          }

          catch (onRejected) {
          ...
          }

          finally(callBack) {
          ...
          }

          static all(promises) {
          ...
          }

          static allSettled(promises) {
          ...
          }


          /**
          * Promise.any()
          * @param {iterable} promises 一個(gè)promise的iterable類(lèi)型(注:Array,Map,Set都屬于ES6的iterable類(lèi)型)的輸入
          * @returns
          */

          + static any(promises) {
          + return new myPromise((resolve, reject) => {
          + // 參數(shù)校驗(yàn)
          + if (Array.isArray(promises)) {
          + let errors = []; //
          + let count = 0; // 計(jì)數(shù)器
          +
          + // 如果傳入的參數(shù)是一個(gè)空的可迭代對(duì)象,則返回一個(gè) 已失?。╝lready rejected) 狀態(tài)的 Promise。
          + if (promises.length === 0) return reject(new AggregateError('All promises were rejected'));
          +
          + promises.forEach(item => {
          + // 非Promise值,通過(guò)Promise.resolve轉(zhuǎn)換為Promise
          + myPromise.resolve(item).then(
          + value => {
          + // 只要其中的一個(gè) promise 成功,就返回那個(gè)已經(jīng)成功的 promise
          + resolve(value);
          + },
          + reason => {
          + cout++;
          + errors.push(reason);
          + /**
          + * 如果可迭代對(duì)象中沒(méi)有一個(gè) promise 成功,就返回一個(gè)失敗的 promise 和AggregateError類(lèi)型的實(shí)例,
          + * AggregateError是 Error 的一個(gè)子類(lèi),用于把單一的錯(cuò)誤集合在一起。
          + */

          + cout === promises.length && reject(new AggregateError(errors));
          + }
          + )
          + })
          + } else {
          + return reject(new TypeError('Argument is not iterable'))
          + }
          + })
          + }
          }

          function resolvePromise(promise2, x, resolve, reject) {
          ...
          }

          module.exports = myPromise;

          使用官方例子測(cè)試一下:

          發(fā)現(xiàn)報(bào)錯(cuò)了,提示 AggregateErro 沒(méi)有定義,這里不是我們代碼的問(wèn)題,是因?yàn)檫@個(gè) AggregateErro ,node v14.15.4?版本沒(méi)有支持,按理說(shuō)這個(gè)版本已經(jīng)很高了,為什么還沒(méi)有支持呢?

          和 Promise.any() 一樣,這個(gè) AggregateError 也是一個(gè)實(shí)驗(yàn)中的功能,處于Stage 3 Draft (第三階段草案):

          我們通過(guò)升級(jí) node 版本來(lái)兼容這些處于草案階段的實(shí)驗(yàn)功能~

          從?node v14.15.4?升級(jí)到最新的?node v16.13.0

          再次驗(yàn)證即可通過(guò):

          用其他用例測(cè)試一下該方法:

          const myPromise = require('../myPromiseFully');

          /**
          * 驗(yàn)證Promise.any()方法
          */


          // console.log(new AggregateError('All promises were rejected'));

          myPromise.any([]).catch(e => {
          console.log(e);
          });

          const pErr = new Promise((resolve, reject) => {
          reject("總是失敗");
          });

          const pSlow = new Promise((resolve, reject) => {
          setTimeout(resolve, 500, "最終完成");
          });

          const pFast = new Promise((resolve, reject) => {
          setTimeout(resolve, 100, "很快完成");
          });

          Promise.any([pErr, pSlow, pFast]).then((value) => {
          console.log(value);
          // 期望輸出: "很快完成"
          })


          const pErr1 = new myPromise((resolve, reject) => {
          reject("總是失敗");
          });

          const pErr2 = new myPromise((resolve, reject) => {
          reject("總是失敗");
          });

          const pErr3 = new myPromise((resolve, reject) => {
          reject("總是失敗");
          });

          myPromise.any([pErr1, pErr2, pErr3]).catch(e => {
          console.log(e);
          })

          輸出結(jié)果:

          AggregateError: All promises were rejected
          AggregateError: All promises were rejected
          很快完成

          測(cè)試通過(guò) ??

          8. 實(shí)現(xiàn) Promise.race()

          Promise.race(iterable)?方法返回一個(gè) promise,一旦迭代器中的某個(gè)promise解決或拒絕,返回的 promise就會(huì)解決或拒絕。

          一個(gè)待定的 Promise 只要給定的迭代中的一個(gè)promise解決或拒絕,就采用第一個(gè)promise的值作為它的返回值,從而異步地解析或拒絕(一旦堆棧為空)。

          race?函數(shù)返回一個(gè)?Promise,它將與第一個(gè)傳遞的 promise 相同的完成方式被完成。它可以是完成( resolves),也可以是失敗(rejects),這要取決于第一個(gè)完成的方式是兩個(gè)中的哪個(gè)。

          • 如果傳的迭代是空的,則返回的 promise 將永遠(yuǎn)等待。

          • 如果迭代包含一個(gè)或多個(gè)非承諾值和/或已解決/拒絕的承諾,則 Promise.race 將解析為迭代中找到的第一個(gè)值。

          根據(jù)規(guī)范我們這樣實(shí)現(xiàn):

          class myPromise {
          ...

          static resolve(value) {
          ...
          }

          static reject(reason) {
          ...
          }

          catch (onRejected) {
          ...
          }

          finally(callBack) {
          ...
          }

          static all(promises) {
          ...
          }

          static allSettled(promises) {
          ...
          }

          static any(promises) {
          ...
          }

          /**
          * Promise.race()
          * @param {iterable} promises 可迭代對(duì)象,類(lèi)似Array。詳見(jiàn) iterable。
          * @returns
          */

          + static race(promises) {
          + return new myPromise((resolve, reject) => {
          + // 參數(shù)校驗(yàn)
          + if (Array.isArray(promises)) {
          + // 如果傳入的迭代promises是空的,則返回的 promise 將永遠(yuǎn)等待。
          + if (promises.length > 0) {
          + promises.forEach(item => {
          + /**
          + * 如果迭代包含一個(gè)或多個(gè)非承諾值和/或已解決/拒絕的承諾,
          + * 則 Promise.race 將解析為迭代中找到的第一個(gè)值。
          + */

          + myPromise.resolve(item).then(resolve, reject);
          + })
          + }
          + } else {
          + return reject(new TypeError('Argument is not iterable'))
          + }
          + })
          + }
          }

          function resolvePromise(promise2, x, resolve, reject) {
          ...
          }

          module.exports = myPromise;

          最后測(cè)試一下代碼:

          const myPromise = require('../myPromiseFully');

          /**
          * 驗(yàn)證Promise.race()方法
          */


          // 數(shù)組全是非Promise值,測(cè)試通過(guò)
          let p1 = myPromise.race([1, 3, 4]);
          setTimeout(() => {
          console.log('p1 :>> ', p1);
          });

          // 空數(shù)組,測(cè)試通過(guò)
          let p2 = myPromise.race([]);
          setTimeout(() => {
          console.log('p2 :>> ', p2);
          });

          const p11 = new myPromise((resolve, reject) => {
          setTimeout(resolve, 500, 'one');
          });

          const p22 = new myPromise((resolve, reject) => {
          setTimeout(resolve, 100, 'two');
          });

          // // 數(shù)組里有非Promise值,測(cè)試通過(guò)
          myPromise.race([p11, p22, 10]).then((value) => {
          console.log('p3 :>> ', value);
          // Both resolve, but p22 is faster
          });
          // expected output: 10

          // 數(shù)組里有'已解決的Promise' 和 非Promise值 測(cè)試通過(guò)
          let p12 = myPromise.resolve('已解決的Promise')
          setTimeout(() => {
          myPromise.race([p12, p22, 10]).then((value) => {
          console.log('p4 :>> ', value);
          });
          // expected output:已解決的Promise
          });

          // Promise.race的一般情況 測(cè)試通過(guò)
          const p13 = new myPromise((resolve, reject) => {
          setTimeout(resolve, 500, 'one');
          });

          const p14 = new myPromise((resolve, reject) => {
          setTimeout(resolve, 100, 'two');
          });

          myPromise.race([p13, p14]).then((value) => {
          console.log('p5 :>> ', value);
          // Both resolve, but promise2 is faster
          });
          // expected output: "two"

          輸出結(jié)果為:

          p1 :>>  myPromise {PromiseState: 'pending', PromiseResult: null, onFulfilledCallbacks: Array(0), onRejectedCallbacks: Array(0)}
          p2 :>> myPromise {PromiseState: 'pending', PromiseResult: null, onFulfilledCallbacks: Array(0), onRejectedCallbacks: Array(0)}
          p3 :>> 10
          p4 :>> 已解決的Promise
          p5 :>> two

          測(cè)試通過(guò) ??????

          完整代碼

          手寫(xiě) Promise 全部方法的完整版代碼較長(zhǎng),這里如果看不清楚的可以去我的GitHub上看:

          • 手寫(xiě) Promise 核心原理,完整的 Promise/A+ 實(shí)現(xiàn),通過(guò)了 Promise/A+ 官方872個(gè)測(cè)試用例測(cè)試,根據(jù)規(guī)范實(shí)現(xiàn)了 ES6+ 的全部 API,包括處于 TC39 第四階段草案的 Promise.any()??https://github.com/yuanyuanbyte/Promise


          /**
          * 在 myPromise.js 基礎(chǔ)上,根據(jù)規(guī)范實(shí)現(xiàn)了 Promise 的全部方法:
          * - Promise.resolve()
          * - Promise.reject()
          * - Promise.prototype.catch()
          * - Promise.prototype.finally()
          * - Promise.all()
          * - Promise.allSettled()
          * - Promise.any()
          * - Promise.race()
          */

          class myPromise {
          static PENDING = 'pending';
          static FULFILLED = 'fulfilled';
          static REJECTED = 'rejected';

          constructor(func) {
          this.PromiseState = myPromise.PENDING;
          this.PromiseResult = null;
          this.onFulfilledCallbacks = [];
          this.onRejectedCallbacks = [];
          try {
          func(this.resolve.bind(this), this.reject.bind(this));
          } catch (error) {
          this.reject(error)
          }
          }

          resolve(result) {
          if (this.PromiseState === myPromise.PENDING) {
          setTimeout(() => {
          this.PromiseState = myPromise.FULFILLED;
          this.PromiseResult = result;
          this.onFulfilledCallbacks.forEach(callback => {
          callback(result)
          })
          });
          }
          }

          reject(reason) {
          if (this.PromiseState === myPromise.PENDING) {
          setTimeout(() => {
          this.PromiseState = myPromise.REJECTED;
          this.PromiseResult = reason;
          this.onRejectedCallbacks.forEach(callback => {
          callback(reason)
          })
          });
          }
          }

          /**
          * [注冊(cè)fulfilled狀態(tài)/rejected狀態(tài)對(duì)應(yīng)的回調(diào)函數(shù)]
          * @param {function} onFulfilled fulfilled狀態(tài)時(shí) 執(zhí)行的函數(shù)
          * @param {function} onRejected rejected狀態(tài)時(shí) 執(zhí)行的函數(shù)
          * @returns {function} newPromsie 返回一個(gè)新的promise對(duì)象
          */

          then(onFulfilled, onRejected) {
          onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
          onRejected = typeof onRejected === 'function' ? onRejected : reason => {
          throw reason;
          };

          let promise2 = new myPromise((resolve, reject) => {
          if (this.PromiseState === myPromise.FULFILLED) {
          setTimeout(() => {
          try {
          let x = onFulfilled(this.PromiseResult);
          resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
          reject(e);
          }
          });
          } else if (this.PromiseState === myPromise.REJECTED) {
          setTimeout(() => {
          try {
          let x = onRejected(this.PromiseResult);
          resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
          reject(e)
          }
          });
          } else if (this.PromiseState === myPromise.PENDING) {
          this.onFulfilledCallbacks.push(() => {
          setTimeout(() => {
          try {
          let x = onFulfilled(this.PromiseResult);
          resolvePromise(promise2, x, resolve, reject)
          } catch (e) {
          reject(e);
          }
          });
          });
          this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
          try {
          let x = onRejected(this.PromiseResult);
          resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
          reject(e);
          }
          });
          });
          }
          })

          return promise2
          }

          /**
          * Promise.resolve()
          * @param {[type]} value 要解析為 Promise 對(duì)象的值
          */

          static resolve(value) {
          // 如果這個(gè)值是一個(gè) promise ,那么將返回這個(gè) promise
          if (value instanceof myPromise) {
          return value;
          } else if (value instanceof Object && 'then' in value) {
          // 如果這個(gè)值是thenable(即帶有`"then" `方法),返回的promise會(huì)“跟隨”這個(gè)thenable的對(duì)象,采用它的最終狀態(tài);
          return new myPromise((resolve, reject) => {
          value.then(resolve, reject);
          })
          }

          // 否則返回的promise將以此值完成,即以此值執(zhí)行`resolve()`方法 (狀態(tài)為fulfilled)
          return new myPromise((resolve) => {
          resolve(value)
          })
          }

          /**
          * Promise.reject()
          * @param {*} reason 表示Promise被拒絕的原因
          * @returns
          */

          static reject(reason) {
          return new myPromise((resolve, reject) => {
          reject(reason);
          })
          }

          /**
          * Promise.prototype.catch()
          * @param {*} onRejected
          * @returns
          */

          catch (onRejected) {
          return this.then(undefined, onRejected)
          }

          /**
          * Promise.prototype.finally()
          * @param {*} callBack 無(wú)論結(jié)果是fulfilled或者是rejected,都會(huì)執(zhí)行的回調(diào)函數(shù)
          * @returns
          */

          finally(callBack) {
          return this.then(callBack, callBack)
          }

          /**
          * Promise.all()
          * @param {iterable} promises 一個(gè)promise的iterable類(lèi)型(注:Array,Map,Set都屬于ES6的iterable類(lèi)型)的輸入
          * @returns
          */

          static all(promises) {
          return new myPromise((resolve, reject) => {
          // 參數(shù)校驗(yàn)
          if (Array.isArray(promises)) {
          let result = []; // 存儲(chǔ)結(jié)果
          let count = 0; // 計(jì)數(shù)器

          // 如果傳入的參數(shù)是一個(gè)空的可迭代對(duì)象,則返回一個(gè)已完成(already resolved)狀態(tài)的 Promise
          if (promises.length === 0) {
          return resolve(promises);
          }

          promises.forEach((item, index) => {
          // 判斷參數(shù)是否為promise
          if (item instanceof myPromise) {
          myPromise.resolve(item).then(
          value => {
          count++;
          // 每個(gè)promise執(zhí)行的結(jié)果存儲(chǔ)在result中
          result[index] = value;
          // Promise.all 等待所有都完成(或第一個(gè)失?。?/span>
          count === promises.length && resolve(result);
          },
          reason => {
          /**
          * 如果傳入的 promise 中有一個(gè)失?。╮ejected),
          * Promise.all 異步地將失敗的那個(gè)結(jié)果給失敗狀態(tài)的回調(diào)函數(shù),而不管其它 promise 是否完成
          */

          reject(reason);
          }
          )
          } else {
          // 參數(shù)里中非Promise值,原樣返回在數(shù)組里
          count++;
          result[index] = item;
          count === promises.length && resolve(result);
          }
          })
          } else {
          return reject(new TypeError('Argument is not iterable'))
          }
          })
          }

          /**
          * Promise.allSettled()
          * @param {iterable} promises 一個(gè)promise的iterable類(lèi)型(注:Array,Map,Set都屬于ES6的iterable類(lèi)型)的輸入
          * @returns
          */

          static allSettled(promises) {
          return new myPromise((resolve, reject) => {
          // 參數(shù)校驗(yàn)
          if (Array.isArray(promises)) {
          let result = []; // 存儲(chǔ)結(jié)果
          let count = 0; // 計(jì)數(shù)器

          // 如果傳入的是一個(gè)空數(shù)組,那么就直接返回一個(gè)resolved的空數(shù)組promise對(duì)象
          if (promises.length === 0) return resolve(promises);

          promises.forEach((item, index) => {
          // 非promise值,通過(guò)Promise.resolve轉(zhuǎn)換為promise進(jìn)行統(tǒng)一處理
          myPromise.resolve(item).then(
          value => {
          count++;
          // 對(duì)于每個(gè)結(jié)果對(duì)象,都有一個(gè) status 字符串。如果它的值為 fulfilled,則結(jié)果對(duì)象上存在一個(gè) value 。
          result[index] = {
          status: 'fulfilled',
          value
          }
          // 所有給定的promise都已經(jīng)fulfilled或rejected后,返回這個(gè)promise
          count === promises.length && resolve(result);
          },
          reason => {
          count++;
          /**
          * 對(duì)于每個(gè)結(jié)果對(duì)象,都有一個(gè) status 字符串。如果值為 rejected,則存在一個(gè) reason 。
          * value(或 reason )反映了每個(gè) promise 決議(或拒絕)的值。
          */

          result[index] = {
          status: 'rejected',
          reason
          }
          // 所有給定的promise都已經(jīng)fulfilled或rejected后,返回這個(gè)promise
          count === promises.length && resolve(result);
          }
          )
          })
          } else {
          return reject(new TypeError('Argument is not iterable'))
          }
          })
          }

          /**
          * Promise.any()
          * @param {iterable} promises 一個(gè)promise的iterable類(lèi)型(注:Array,Map,Set都屬于ES6的iterable類(lèi)型)的輸入
          * @returns
          */

          static any(promises) {
          return new myPromise((resolve, reject) => {
          // 參數(shù)校驗(yàn)
          if (Array.isArray(promises)) {
          let errors = []; //
          let count = 0; // 計(jì)數(shù)器

          // 如果傳入的參數(shù)是一個(gè)空的可迭代對(duì)象,則返回一個(gè) 已失敗(already rejected) 狀態(tài)的 Promise。
          if (promises.length === 0) return reject(new AggregateError([], 'All promises were rejected'));

          promises.forEach(item => {
          // 非Promise值,通過(guò)Promise.resolve轉(zhuǎn)換為Promise
          myPromise.resolve(item).then(
          value => {
          // 只要其中的一個(gè) promise 成功,就返回那個(gè)已經(jīng)成功的 promise
          resolve(value);
          },
          reason => {
          count++;
          errors.push(reason);
          /**
          * 如果可迭代對(duì)象中沒(méi)有一個(gè) promise 成功,就返回一個(gè)失敗的 promise 和AggregateError類(lèi)型的實(shí)例,
          * AggregateError是 Error 的一個(gè)子類(lèi),用于把單一的錯(cuò)誤集合在一起。
          */

          count === promises.length && reject(new AggregateError(errors, 'All promises were rejected'));
          }
          )
          })
          } else {
          return reject(new TypeError('Argument is not iterable'))
          }
          })
          }

          /**
          * Promise.race()
          * @param {iterable} promises 可迭代對(duì)象,類(lèi)似Array。詳見(jiàn) iterable。
          * @returns
          */

          static race(promises) {
          return new myPromise((resolve, reject) => {
          // 參數(shù)校驗(yàn)
          if (Array.isArray(promises)) {
          // 如果傳入的迭代promises是空的,則返回的 promise 將永遠(yuǎn)等待。
          if (promises.length > 0) {
          promises.forEach(item => {
          /**
          * 如果迭代包含一個(gè)或多個(gè)非承諾值和/或已解決/拒絕的承諾,
          * 則 Promise.race 將解析為迭代中找到的第一個(gè)值。
          */

          myPromise.resolve(item).then(resolve, reject);
          })
          }
          } else {
          return reject(new TypeError('Argument is not iterable'))
          }
          })
          }
          }

          /**
          * 對(duì)resolve()、reject() 進(jìn)行改造增強(qiáng) 針對(duì)resolve()和reject()中不同值情況 進(jìn)行處理
          * @param {promise} promise2 promise1.then方法返回的新的promise對(duì)象
          * @param {[type]} x promise1中onFulfilled或onRejected的返回值
          * @param {[type]} resolve promise2的resolve方法
          * @param {[type]} reject promise2的reject方法
          */

          function resolvePromise(promise2, x, resolve, reject) {
          if (x === promise2) {
          return reject(new TypeError('Chaining cycle detected for promise'));
          }

          if (x instanceof myPromise) {
          if (x.PromiseState === myPromise.PENDING) {
          x.then(y => {
          resolvePromise(promise2, y, resolve, reject)
          }, reject);
          } else if (x.PromiseState === myPromise.FULFILLED) {
          resolve(x.PromiseResult);
          } else if (x.PromiseState === myPromise.REJECTED) {
          reject(x.PromiseResult);
          }
          } else if (x !== null && ((typeof x === 'object' || (typeof x === 'function')))) {
          try {
          var then = x.then;
          } catch (e) {
          return reject(e);
          }

          if (typeof then === 'function') {
          let called = false;
          try {
          then.call(
          x,
          y => {
          if (called) return;
          called = true;
          resolvePromise(promise2, y, resolve, reject);
          },
          r => {
          if (called) return;
          called = true;
          reject(r);
          }
          )
          } catch (e) {
          if (called) return;
          called = true;

          reject(e);
          }
          } else {
          resolve(x);
          }
          } else {
          return resolve(x);
          }
          }

          myPromise.deferred = function () {
          let result = {};
          result.promise = new myPromise((resolve, reject) => {
          result.resolve = resolve;
          result.reject = reject;
          });
          return result;
          }

          module.exports = myPromise;

          ?? 結(jié)尾

          如果這篇文章?對(duì)你的學(xué)習(xí)?有所?幫助,歡迎?點(diǎn)贊????收藏???留言??? ,你的支持?是我?創(chuàng)作分享?的?動(dòng)力!

          關(guān)注公眾號(hào)「前端圓圓」,第一時(shí)間獲取最新的文章更新。

          更多更全更詳細(xì)?的?優(yōu)質(zhì)內(nèi)容,?猛戳這里查看

          參考

          ????????鏈接放在最下面了

          • Promises/A+ (promisesaplus.com)

          • Promise A+ 規(guī)范 (malcolmyu.github.io)

          • 手寫(xiě)Promise核心代碼

          • Promise詳解與實(shí)現(xiàn)(Promise/A+規(guī)范)

          • 手寫(xiě)一個(gè)Promise/A+,完美通過(guò)官方872個(gè)測(cè)試用例

          • 剖析Promise內(nèi)部結(jié)構(gòu),一步一步實(shí)現(xiàn)一個(gè)完整的、能通過(guò)所有Test case的Promise類(lèi)

          • Promise.prototype.then() - JavaScript | MDN (mozilla.org)

          • Promise.prototype.catch() - JavaScript | MDN (mozilla.org)

          • 從一道讓我失眠的 Promise 面試題開(kāi)始,深入分析 Promise 實(shí)現(xiàn)細(xì)節(jié)

          • 手寫(xiě)Promise - 常用靜態(tài)方法all、resolve、reject、race

          • 手寫(xiě)Promise - 實(shí)例方法catch、finally

          • 手寫(xiě)Promise周邊方法

          • Promise.any 的作用,如何自己實(shí)現(xiàn)一個(gè) Promise.any

          參考文章鏈接

          • https://promisesaplus.com

          • https://malcolmyu.github.io/2015/06/12/Promises-A-Plus

          • https://www.bilibili.com/video/BV1RR4y1p7my?from=search&seid=14552865939751412953

          • https://www.jianshu.com/p/459a856c476f

          • https://www.cnblogs.com/dennisj/p/12660388.html

          • https://github.com/xieranmaya/blog/issues/3

          • https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/then

          • https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch

          • https://juejin.cn/post/6945319439772434469#heading-19

          • https://segmentfault.com/a/1190000023379900

          • https://segmentfault.com/a/1190000023279746

          • https://zhuanlan.zhihu.com/p/143699690

          • https://zhuanlan.zhihu.com/p/374679042




          瀏覽 53
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产内射免费视频 | 欧洲无码免费视频 | 欧美 中文 日韩 | 日韩中文字幕区 | 国产激情性爱小说视频 |