Promise 的概念、用法与实现(基于TypeScript的源码)

举报
jcLee95 发表于 2023/06/09 21:01:38 2023/06/09
【摘要】 Promise 的概念、用法与实现作者: 李俊才(CSDN:jcLee95)邮箱 :291148484@163.comCSDN 主页:https://blog.csdn.net/qq_28550263?spm=1001.2101.3001.5343本文地址:https://blog.csdn.net/qq_28550263/article/details/121506948相关文章:dart...
Promise 的概念、用法与实现

邮箱 :291148484@163.com

目 录



Promise 是一个对象,它代表了一个异步操作的最终完成或者失败在其它一些语言如dart中也有这个概念,但叫做Future,表示将来。执行一个异步操作,在其执行前并不知道其最终执行会成功(即顺利完成:FULFILLED)或者会失败(即所谓拒绝:REJECTED),这时我们称这个一部操作执行的状态为待定(PENDING)

  • Promise 含义为“承若”,用于表示 一个异步操作的 最终完成/失败 及其 结果值
  • 一个 Promise 对象代表一个在这个 promise 被创建出来时不一定已知的值

它让您能够把异步操作最终的成功返回值或者失败原因相应的处理程序关联起来

这样使得异步方法可以像同步方法那样返回值:异步方法并不会立即返回最终的值,而是会返回一个 promise,以便在未来某个时候把值交给使用者。

在这里插入图片描述





p.then(onFulfilled[, onRejected]);

该方法接受两个可选的回调,分别表示构造该 Promise 对象实例时,执行构造器函数后,实例状态由 pending 进入fulfilled 或者 rejected 后,所执行的回调。

也就是说:

  • 若该实例的状态由 pending 进入fulfilled 则执行 onFulfilled 回调;
  • 若该实例的状态由 pending 进入rejected 则执行 onRejected 回调;
参数 类型 描述
onFulfilled ((value: any) => void | Thenable<void>) | null | undefined 当 Promise 变成接受状态(fulfilled)时调用的函数。
onRejected ((reason: any) => void | Thenable<void>) | null | undefined 当 Promise 变成拒绝状态(rejected)时调用的函数。

其中,这里的 Thenable 也被称作 PromiseLike,表示实现了这样一个 then 方法的对象,见 5.1 Thenable 接口 小节。


当一个 Promise 完成(fulfilled)或者失败(rejected)时,返回函数将被异步调用(由当前的线程循环来调度完成)。具体的返回值依据以下规则返回。如果 then 中的回调函数:

回调函数的返回值 then 返回的新 Promise
已接受的 Promise 对象实例 也会成为接受状态(fulfilled),
并且将那个 Promise 的接受状态的回调函数的参数值作为该被返回的 Promise 的接受状态回调函数的参数值。
已拒绝的 Promise 对象实例 也会成为拒绝状态(rejected),
并且将那个 Promise 的拒绝状态的回调函数的参数值作为该被返回的 Promise 的拒绝状态回调函数的参数值。
不是 Promise实例的其它值 将会成为接受状态(fulfilled),
并且将返回的值作为接受状态的回调函数的参数值。
没有返回任何值 将会成为接受状态(fulfilled),
并且该接受状态的回调函数的参数值为 undefined。
抛出异常 将会成为拒绝状态(rejected),
并且将抛出的错误作为拒绝状态的回调函数的参数值。
针对异步情况 返回一个未定状态(pending)的 Promise,那么 then 返回 Promise 的状态也是未定的,
并且它的终态与那个 Promise 的终态相同;
同时,它变为终态时调用的回调函数参数与那个 Promise 变为终态时的回调函数的参数是相同的。

最简单的示例:

function excutor(resolve, reject) {
  // do something others ...
  // ...
    
  resolve('成功返回值');  // 调用传入执行器函数的 resolve 函数
}

let p1 = new Promise(excutor(resolve, reject));

p1.then(
  // 成功时执行的回调
  (value) => {
    console.log(value); // 成功返回值
  }, 
  // 失败时执行的回调
  (reason) => {
    console.error(reason); // 出错了!
  }
);

这个例子中,在执行器中执行了传入的 resolve 函数,使得 Promise 由 pending 状态进入了 fulfilled 状态。


在构造 Promise 对象时需要传入一个函数,称之为 执行器函数。这个函数有两个参数,分别是当前 Promsie 对象进入 成功/实现(fulfilled)、失败/拒绝(rejected) 这两个状态时的 回调函数。这两个函数的主要作用是,让我们(Promise对象的使用者)可以在执行器函数体内改变其状态,也就是实现 Promise 状态 分支 的作用。

也就是说,一个 Promise 对象构造之初为 pending状态 。通过调用不同的回调函数(resolve 或 reject),可以进而进入 fulfilled 状态 或 reject 状态。在前面的例子中,为了能让大家看得更清楚,我们是单独在外定义执行器函数的:

function excutor(resolve, reject) {
  // ...
  resolve('成功返回值');  // 调用传入执行器函数的 resolve 函数
}

然后我们将这个函数的执行后的结果作为 Promise 构造器函数的参数:

new Promise(excutor(resolve, reject));

但是显然你不能单独在Promise的构造器外调用执行器函数,获取该函数的返回值再传递给Promise的构造器:

let e = excutor(resolve, reject); // resolve & reject is not defined!
let p = new Promise(e);

这将产生 resolve 和 reject 没有定义的报错。这是因为,resolve 和 reject 这两个函数不是我们定义的,而是在 Promise 的构造器中进行定义的,使用 new Promise(excutor(resolve, reject)); 语句时,由 Promise 的构造器调传入了这两个参数。

作为 Promise 的使用者, 我们使用 resolve 和 reject 这两个在 Promise 内定义的回调函数,除了用于决定当前 Promise 将按照我们的规则进入那种状态(fulfilled 或 rejected)外,还有就是传入这两个状态该下需要传递的值:

  • 如果使用 resolve(value) 回调函数,表明当前 Promise 将进入 成功/兑现/实现 (fulfilled) 状态,这时根据需要一个传入resolve函数返回值,作为进一步处理的参数。
  • 如果使用 reject(reason) 回调函数,表明当前 Promise 将进入 失败/拒绝 (rejected) 状态,这时可以通过传入reject函数一个描述失败原因的值,以方便追踪为什么进入失败。

Promise 能够进行作为链式调用的原因在于,其 then 方法返回的也是一个 Promise 对象。

p.catch(onRejected);

p.catch(function(reason) {
   // 拒绝回调函数体
});

catch() 方法返回一个新的 Promise 对象的实例,并且处理拒绝的情况。它的行为与调用Promise.prototype.then(undefined, onRejected) 相同。
事实上,calling obj.catch(onRejected) 内部调用了 obj.then(undefined, onRejected) 方法。

例如:

var p = new Promise(function(resolve, reject) {
  throw 'Uh-oh!';
});

p.catch(function(e) {
  console.log(e); // "Uh-oh!"
});

在异步函数中抛出的错误不会被 catch 捕获到,例如:

var p2 = new Promise(function(resolve, reject) {
  setTimeout(function() {
    throw 'Uncaught Exception!';
  }, 1000);
});

p2.catch(function(e) {
  console.log(e); // 不会执行
});

在 resolve() 后面抛出的错误会被忽略,例如

var p3 = new Promise(function(resolve, reject) {
  resolve();
  throw 'Silenced Exception!';
});

p3.catch(function(e) {
   console.log(e); // 不会执行
});

finally() 方法返回一个 Promise。在 promise 结束时,无论结果是 fulfilled 或者是 rejected,都会执行指定的回调函数。这为在 Promise 是否成功完成后都需要执行的代码提供了一种方式。这避免了同样的语句需要在 then() 和 catch() 中各写一次的情况。

p.finally(onFinally);

p.finally(function() {
   // 返回状态为 (resolved 或 rejected)
});


语法格式

Promise.any(iterable);

功能描述

该方法接收一个由 Promise 所组成的可迭代对象,并返回一个新的 promise:

  • 一旦可迭代对象内的任意一个 promise 变成了兑现状态,那么所返回的新 promise 就会变成兑现状态,并且它的兑现值就是可迭代对象内的首先兑现的 promise 的兑现值。
  • 如果可迭代对象内的所有 promise 最终都被拒绝,那么该方法所返回的 promise 就会变成拒绝状态,并且它的拒因会是一个 AggregateError 实例,这是 Error 的子类,用于把单一的错误集合在一起。

Promise.allSettled() 方法返回一个在所有给定的 promise 都已经fulfilled或rejected后的 promise,并带有一个对象数组,每个对象表示对应的 promise 结果。

当您有多个彼此不依赖的异步任务成功完成时,或者您总是想知道每个promise的结果时,通常使用它。

相比之下,Promise.all() 更适合彼此相互依赖或者在其中任何一个reject时立即结束。

语法格式

Promise.allSettled(iterable);

参数

参数 描述
iterable 一个可迭代的对象,例如Array,其中每个成员都是Promise。

Promise.any() 接收一个由 Promise 所组成的可迭代对象,该方法会返回一个新的 promise,一旦可迭代对象内的任意一个 promise 变成了兑现状态,那么由该方法所返回的 promise 就会变成兑现状态,并且它的兑现值就是可迭代对象内的首先兑现的 promise 的兑现值。如果可迭代对象内的 promise 最终都没有兑现(即所有 promise 都被拒绝了),那么该方法所返回的 promise 就会变成拒绝状态。

语法格式

Promise.any(iterable);

参数

参数 描述
iterable 一个可迭代的对象,例如Array,其中每个成员都是Promise。

该方法返回一个 Promise 实例,一旦迭代器中的某个 promise 解决或拒绝,返回的 promise 就会解决或拒绝。

语法格式

Promise.race(iterable);

参数

参数 描述
iterable 一个可迭代的对象,例如Array,其中每个成员都是Promise。

该方法方法返回一个带有拒绝原因的 Promise 实例。

语法格式

Promise.reject(reason);

参数

参数 描述
reason 表示Promise被拒绝的原因

该方法返回一个以给定值解析后的 Promise 对象。如果这个值是一个 promise,那么将返回这个 promise;如果这个值是 thenable(即带有 “then” 方法),返回的 promise 会“跟随”这个 thenable 的对象,采用它的最终状态;否则返回的 promise 将以此值完成。此函数将类 promise 对象的多层嵌套展平。

语法格式

Promise.resolve(value);

参数

参数 描述
value 将被 Promise 对象解析的参数,也可以是一个Promise 对象,或者是一个 thenable。

返回值

返回一个带着给定值解析过的 Promise 对象,如果参数本身就是一个 Promise 对象,则直接返回这个 Promise 对象。


本小节中,由于 ES6 以后直接为我们提供了 Promise 对象,在我们自己对其进行实现时,不再以 Promise 作为名字,转而使用 Future


事实上 Promise 可以看作时一个 thenable 接口的实现,实现 thenable 的对象也可以称作 Promise Like 对象:

interface Thenable<T> {
  then<TResult1 = T, TResult2 = never>(
    onfulfilled?:
      | ((value: T) => TResult1 | Thenable<TResult1>)
      | undefined
      | null,
    onrejected?:
      | ((reason: any) => TResult2 | Thenable<TResult2>)
      | undefined
      | null
  ): Thenable<TResult1 | TResult2>;
}

enum FutureState {
  PENDING = "pending",
  FULFILL = "fulfilled",
  REJECT = "rejected",
}

先声明一个容纳回调的容器接口:

declare type callbacktype = {
  onfulfilled?: ((value: any) => void | Thenable<void>) | null | undefined;
  onrejected?: ((reason: any) => void | Thenable<void>) | null | undefined;
};

下面的代码仅给出 Promise 属性 和 构造器

class Future<T> {
  private _state: FutureState;
  private _result: T | Thenable<T> | undefined;
  private _callbacks: callbacktype[] = [];

  constructor(
    executor: (
      resolve: (value: T | Thenable<T>) => void,
      reject: (reason?: any) => void
    ) => void
  ) {
    // 初始化状态为 PEDDING
    this._state = FutureState.PENDING;

    // 很重要
    // 因为 this 在新定义的函数内会改变指向
    let self = this;

    function _resolve(value: T | Thenable<T>) {
      // 一个 Future 对象的状态只改变一次
      if (self._state === FutureState.PENDING) {
        self._state = FutureState.FULFILL;
        self._result = value;
      }

      // 对于异步任务,成功时回调执行
      self._callbacks.forEach(
        // 多个回调分别执行
        (callback) => {
          if (callback.onfulfilled) {
            callback.onfulfilled(value);
          }
        }
      );
    }

    function _reject(reason?: any) {
      // 一个 Future 对象的状态只改变一次
      if (self._state === FutureState.PENDING) {
        self._state = FutureState.REJECT;
        self._result = reason;
      }

      // 对于异步任务,失败时回调执行
      self._callbacks.forEach((callback) => {
        if (callback.onrejected) {
          callback.onrejected(reason);
        }
      });
    }

    // 调用执行器函数
    try {
      executor(_resolve, _reject);
    } catch (error) {
      _reject(error);
    }
  }
// ...
}

then 方法为 Promise 实例方法
Promise.prototype.then()

以下代码仅给出 then 方法:

class Future<T> {
  // ...
   then(
    onfulfilled?: ((value: any) => void | Thenable<void>) | null | undefined,
    onrejected?: ((reason: any) => void | Thenable<void>) | null | undefined
  ) {
    // 返回值也是一个 Future 对象的实例,
    // 并且:
    // - 如果当前层回调不返回 Future:
    //   则实例状态取决于当前回调函数中所改变的状态是 FULFILL 还是 REJECT
    // - 如果前层回调返回的也是 Future 实例,且当前执行器函数中本身为成功:
    //   则当前实例成功还是失败的状态取决于回调函数返回的 Future 实例状态是 FULFILL 还是 REJECT

    // 很重要,确保在新对象里面能由变量指向当前对象
    let self = this;

    // 要能够在没有传递回调时正常地完成链式调用,需要定义默认地回调函数
    // 1. 若 onfulfilled 没有定义
    if (typeof onfulfilled !== "function") {
      onfulfilled = (value) => {
        return value;
      };
    }
    // 2. 若 onrejected 没有定义
    if (typeof onrejected !== "function") {
      onrejected = (reason) => {
        throw reason;
      };
    }

    return new Future((resolve, reject) => {
      // 执行器回调函数,可能是 成功的回调 onfulfilled 也可能是 失败的回调 onrejected
      function callback(callbackType: {
        (value: any): void | Thenable<void>;
        (reason: any): void | Thenable<void>;
        (value: any): void | Thenable<void>;
        (reason: any): void | Thenable<void>;
        (arg0: T | Thenable<T> | undefined): any;
      }) {
        // 获取回调函数的返回值
        let res = callbackType(self._result);
        // 如果回调的返回值类型是 Future 对象实例
        if (res instanceof Future) {
          res.then(
            // 若返回的 Future 接受,则返回接受的返回值(传递 Future 链成功的返回值)
            (returns) => {
              resolve(returns);
            },
            // 若返回的 Future 拒绝,则返回拒绝的原因(传递 Future 链 拒绝和拒绝原因)
            (reason) => {
              reject(reason);
            }
          );
          // 若不是 Future 对象的实例,则返的 Future 进入接受状态
          // 且传递 接受回调(callback 为 onfulfilled时) 的 返回值
        } else {
          resolve(res);
        }
      }

      // 1. FULFILL: 如果成功,则执行成功的回调
      if (self._state === FutureState.FULFILL) {
        // 若调用回调异常也应导致 Future 状态为 REJECT
        try {
          // 异步执行
          setTimeout(() => {
            callback(onfulfilled as (value: any) => void);
          });
        } catch (error) {
          reject(error);
        }
      }
      // 2. REJECT: 如果失败,则执行失败的回调
      else if (self._state === FutureState.REJECT) {
        try {
          setTimeout(() => {
            callback(onrejected as (reason: any) => void | Thenable<void>);
          });
        } catch (error) {
          reject(error);
        }
      }
      // 3. PENDING: 针对于异步任务,状态仍是 PENDING 时需要保存回调函数
      // 执行器执行异步任务中调用 then 方法时,还不知道成功或者失败,
      // 因此只好同时将 成功的回调onfulfilled 和失败的回调onrejected 先同时保存
      // 待到执行器执行完异步任务后,在执行器中调用成功或者失败的回调时、或者直接
      // 因为执行器执行失败,在 then 方法 catch 块调用的 reject() 时,
      // 再执行这些相应的回调
      else if (self._state === FutureState.PENDING) {
        self._callbacks.push({
          onfulfilled: function () {
            try {
              callback(onfulfilled as (value: any) => void | Thenable<void>);
            } catch (error) {
              reject(error);
            }
          },
          onrejected: function () {
            try {
              callback(onrejected as (reason: any) => void | Thenable<void>);
            } catch (error) {
              reject(error);
            }
          },
        });
      } else {
        console.log("Future State is:", self._state);
        throw "FutureStateError : Got an error status.";
      }
    });
  }
  // ...
}

catch 方法为 Promise 实例方法
Promise.prototype.catch()

class Future<T> {

  // ...
  catch<TResult = never>(
    onrejected?:
      | ((reason: any) => TResult | Thenable<TResult>)
      | undefined
      | null
  ): Future<T | TResult> {
    return this.then(undefined, onrejected);
  }
  // ...
}

finally 方法为 Promise 实例方法
Promise.prototype.finally()

class Future<T> {

  // ...
  finally(onfinally?: (() => void) | undefined | null): Future<T> {
    if(typeof onfinally !== "function"){
      onfinally = () => {
        return;
      };
    }
    return this.then(
      (value)=>{
        return Future.resolve((onfinally as (() => void))()).then(
            ()=>value
          )
      },
      (reason)=>{
        return Future.resolve((onfinally as (() => void))()).then(
          ()=>{throw reason}
        )
      }
    )
  }
  // ...

all 方法为 Promise 静态方法
Promise.all(iterable)

这个方法返回一个新的 promise 对象,等到所有的 promise 对象都成功或有任意一个 promise 失败。

如果所有的 promise 都成功了,它会把一个包含 iterable 里所有 promise 返回值的数组作为成功回调的返回值。顺序跟 iterable 的顺序保持一致。

一旦有任意一个 iterable 里面的 promise 对象失败则立即以该 promise 对象失败的理由来拒绝这个新的 promise。

class Future<T> {
  // ...
  static all<T>(iterable: Iterable<Future<T>>) {
    let ct = 0;
    let length = 0;
    let arr: any[] = [];
    return new Future((resolve, reject) => {
      for (let future of iterable) {
        length = length + 1;
        future.then(
          (value: any) => {
            ct = ct + 1;
            arr[ct] = value;
          },
          (reason: any) => {
            reject(reason);
          }
        );
      }
      if (length === ct) {
        resolve(arr);
      }
    });
  }
  // ...
}

allSettled 方法为 Promise 静态方法
Promise.allSettled(iterable)

等到所有 promise 都已敲定(每个 promise 都已兑现或已拒绝)。

返回一个 promise,该 promise 在所有 promise 都敲定后完成,并兑现一个对象数组,其中的对象对应每个 promise 的结果。

class Future<T> {
  // ...

  // ...
}

any 方法为 Promise 静态方法
Promise.any(iterable)

接收一个 promise 对象的集合,当其中的任意一个 promise 成功,就返回那个成功的 promise 的值。

class Future<T> {
  // ...
  static any<T>(iterable: Iterable<Future<T>>) {
    return new Future((resolve, reject) => {
      for (let future of iterable) {
        future.then(
          // 某个 future 兑现则新 future 兑现
          (value: any) => {
            resolve(value);
          },
          // 某个 future 拒绝,不做任何处理
          (reason: any) => {}
        );
      }
    });
  }
  // ...
}

race 方法为 Promise 静态方法
Promise.race(iterable)

等到任意一个 promise 的状态变为已敲定。

当 iterable 参数里的任意一个子 promise 成功或失败后,父 promise 马上也会用子 promise 的成功返回值或失败详情作为参数调用父 promise 绑定的相应处理函数,并返回该 promise 对象。

class Future<T> {
  // ...
  race<T>(iterable: Iterable<Future<T>>) {
    return new Future((resolve, reject) => {
      for (let future of iterable) {
        future.then(
          (value: any) => {
            resolve(value);
          },
          (reason: any) => {
            reject(reason);
          }
        );
      }
    });
  }
  // ...
}

reject 方法为 Promise 静态方法
Promise.reject(reason)

返回一个状态为已拒绝的 Promise 对象,并将给定的失败信息传递给对应的处理函数。

class Future<T> {
  // ...
  static reject(reason?: any): Future<any> {
    return new Future<any>((resolve, reject) => {
      reject(reason);
    });
  }
  // ...
}

resolve 方法为 Promise 静态方法
Promise.resolve(value)

返回一个状态由给定 value 决定的 Promise 对象。如果该值是 thenable(即,带有 then 方法的对象),返回的Promise 对象的最终状态由 then 方法执行结果决定;否则,返回的 Promise 对象状态为已兑现,并且将该 value 传递给对应的 then 方法。

通常而言,如果你不知道一个值是否是 promise 对象,使用 Promise.resolve(value) 来返回一个 Promise 对象,这样就能将该 value 以 promise 对象形式使用。

class Future<T> {
  // ...
  static resolve(): Future<void>; // 重载1
  static resolve<T>(value: T | Thenable<T>): Future<T>;// 重载2
  static resolve<T>(value?: T | Thenable<T>) {
    return new Future((resolve, reject) => {
      if (value instanceof Future) {
        value.then(
          (vl) => {
            resolve(vl);
          },
          (rs) => {
            reject(rs);
          }
        );
      } else {
        resolve(value);
      }
    });
  }
  // ...
}


在我们代码的类型注释中使用通过了高级类型 Awaited。类型 Awaited 表示递归展开一个类型的“awaited type”。非 Promise 的 Thenable 对象 应该 resolve 为 never。这模拟了await的行为。其声明如下:

type Awaited<T> =
    T extends null | undefined ? T : // 不在 `--strictNullChecks` 模式下时 `null | undefined` 的特殊情况
        T extends object & { then(onfulfilled: infer F): any } ? // `await` 只解包带有可调用 `then` 的对象类型。非对象类型不会被展开
            F extends ((value: infer V, ...args: any) => any) ? // 如果 `then`的参数是可调用的,则提取第一个参数
                Awaited<V> : // 递归展开值
                never : // `then` 这个参数是不可调用的
        T; // 非 object 或者 非 thenable

enum FutureState {
  PENDING = "pending",
  FULFILL = "fulfilled",
  REJECT = "rejected",
}

interface Thenable<T> {
  then<TResult1 = T, TResult2 = never>(
    onfulfilled?:
      | ((value: T) => TResult1 | Thenable<TResult1>)
      | undefined
      | null,
    onrejected?:
      | ((reason: any) => TResult2 | Thenable<TResult2>)
      | undefined
      | null
  ): Thenable<TResult1 | TResult2>;
}


interface Future<T> {

  then<TResult1 = T, TResult2 = never>(
    onfulfilled?:
      | ((value: T) => TResult1 | Thenable<TResult1>)
      | undefined
      | null,
    onrejected?:
      | ((reason: any) => TResult2 | Thenable<TResult2>)
      | undefined
      | null
  ): Future<TResult1 | TResult2>;


  catch<TResult = never>(
    onrejected?:
      | ((reason: any) => TResult | Thenable<TResult>)
      | undefined
      | null
  ): Future<T | TResult>;
}


interface FutureFulfilledResult<T> {
  status: "fulfilled";
  value: T;
}

interface FutureRejectedResult {
  status: "rejected";
  reason: any;
}

type FutureSettledResult<T> = FutureFulfilledResult<T> | FutureRejectedResult;


declare type callbacktype = {
  onfulfilled?: ((value: any) => void | Thenable<void>) | null | undefined;
  onrejected?: ((reason: any) => void | Thenable<void>) | null | undefined;
};

class Future<T> {
  private _state: FutureState;
  private _result: T | Thenable<T> | undefined;
  private _callbacks: callbacktype[] = [];

  constructor(
    executor: (
      resolve: (value: T | Thenable<T>) => void,
      reject: (reason?: any) => void
    ) => void
  ) {
    // 初始化状态为 PEDDING
    this._state = FutureState.PENDING;

    // 很重要
    // 因为 this 在新定义的函数内会改变指向
    let self = this;

    function _resolve(value: T | Thenable<T>) {
      // 一个 Future 对象的状态只改变一次
      if (self._state === FutureState.PENDING) {
        self._state = FutureState.FULFILL;
        self._result = value;
      }

      // 对于异步任务,成功时回调异步执行
      setTimeout(() => {
        self._callbacks.forEach(
          // 多个回调分别执行
          (callback) => {
            if (callback.onfulfilled) {
              callback.onfulfilled(value);
            }
          }
        );
      });
    }

    function _reject(reason?: any) {
      // 一个 Future 对象的状态只改变一次
      if (self._state === FutureState.PENDING) {
        self._state = FutureState.REJECT;
        self._result = reason;
      }

      // 对于异步任务,失败时回调异步执行
      setTimeout(() => {
        self._callbacks.forEach((callback) => {
          if (callback.onrejected) {
            callback.onrejected(reason);
          }
        });
      });
    }

    // 调用执行器函数
    try {
      executor(_resolve, _reject);
    } catch (error) {
      _reject(error);
    }
  }

  /**
   * accessor属性返回对象的默认构造函数。子类构造函数可以覆盖它来改变构造函数的赋值。
   * 默认实现基本上是:`@@speciesPromise`
   * @return 调用get @@species的构造函数(this)的值。返回值用于从创建新承诺的承诺链方法中构造返回值。
   */
  static get [Symbol.species]() {
    return this;
  }

  /**
   * 为 Future 添加被兑现和被拒绝状态的回调函数,其以回调函数的返回值兑现 Future。
   * 若不处理已兑现或者已拒绝状态(例如,onFulfilled 或 onRejected 不是一个函数),则返回 Future 被敲定时的值。
   * @param onfulfilled Future 进入成功时的回调
   * @param onrejected Future 进入失败时的回调
   * @returns 一个新的 Future 实例对象,它用于在 Future 链中传递 Future 状态。
   */
  then(
    onfulfilled?: ((value: any) => void | Thenable<void>) | null | undefined,
    onrejected?: ((reason: any) => void | Thenable<void>) | null | undefined
  ) {
    // 返回值也是一个 Future 对象的实例,
    // 并且:
    // - 如果当前层回调不返回 Future:
    //   则实例状态取决于当前回调函数中所改变的状态是 FULFILL 还是 REJECT
    // - 如果前层回调返回的也是 Future 实例,且当前执行器函数中本身为成功:
    //   则当前实例成功还是失败的状态取决于回调函数返回的 Future 实例状态是 FULFILL 还是 REJECT

    // 很重要,确保在新对象里面能由变量指向当前对象
    let self = this;

    // 要能够在没有传递回调时正常地完成链式调用,需要定义默认地回调函数
    // 1. 若 onfulfilled 没有定义
    if (typeof onfulfilled !== "function") {
      onfulfilled = (value) => {
        return value;
      };
    }
    // 2. 若 onrejected 没有定义
    if (typeof onrejected !== "function") {
      onrejected = (reason) => {
        throw reason;
      };
    }

    return new Future((resolve, reject) => {
      // 执行器回调函数,可能是 成功的回调 onfulfilled 也可能是 失败的回调 onrejected
      function callback(callbackType: {
        (value: any): void | Thenable<void>;
        (reason: any): void | Thenable<void>;
        (value: any): void | Thenable<void>;
        (reason: any): void | Thenable<void>;
        (arg0: T | Thenable<T> | undefined): any;
      }) {
        // 获取回调函数的返回值
        let res = callbackType(self._result);
        // 如果回调的返回值类型是 Future 对象实例
        if (res instanceof Future) {
          res.then(
            // 若返回的 Future 接受,则返回接受的返回值(传递 Future 链成功的返回值)
            (returns) => {
              resolve(returns);
            },
            // 若返回的 Future 拒绝,则返回拒绝的原因(传递 Future 链 拒绝和拒绝原因)
            (reason) => {
              reject(reason);
            }
          );
          // 若不是 Future 对象的实例,则返的 Future 进入接受状态
          // 且传递 接受回调(callback 为 onfulfilled时) 的 返回值
        } else {
          resolve(res);
        }
      }

      // 1. FULFILL: 如果成功,则执行成功的回调
      if (self._state === FutureState.FULFILL) {
        // 若调用回调异常也应导致 Future 状态为 REJECT
        try {
          // 异步执行
          setTimeout(() => {
            callback(onfulfilled as (value: any) => void);
          });
        } catch (error) {
          reject(error);
        }
      }
      // 2. REJECT: 如果失败,则执行失败的回调
      else if (self._state === FutureState.REJECT) {
        try {
          setTimeout(() => {
            callback(onrejected as (reason: any) => void | Thenable<void>);
          });
        } catch (error) {
          reject(error);
        }
      }
      // 3. PENDING: 针对于异步任务,状态仍是 PENDING 时需要保存回调函数
      // 执行器执行异步任务中调用 then 方法时,还不知道成功或者失败,
      // 因此只好同时将 成功的回调onfulfilled 和失败的回调onrejected 先同时保存
      // 待到执行器执行完异步任务后,在执行器中调用成功或者失败的回调时、或者直接
      // 因为执行器执行失败,在 then 方法 catch 块调用的 reject() 时,
      // 再执行这些相应的回调
      else if (self._state === FutureState.PENDING) {
        self._callbacks.push({
          onfulfilled: function () {
            try {
              callback(onfulfilled as (value: any) => void | Thenable<void>);
            } catch (error) {
              reject(error);
            }
          },
          onrejected: function () {
            try {
              callback(onrejected as (reason: any) => void | Thenable<void>);
            } catch (error) {
              reject(error);
            }
          },
        });
      } else {
        console.log("Future State is:", self._state);
        throw "FutureStateError : Got an error status.";
      }
    });
  }

  /**
   * 为 Future 添加一个被拒绝状态的回调函数,并返回一个新的 Future,
   * 若回调函数被调用,则兑现其返回值,
   * 否则兑现原来的 Future 兑现的值。
   * @param reason
   */
  catch<TResult = never>(
    onrejected?:
      | ((reason: any) => TResult | Thenable<TResult>)
      | undefined
      | null
  ): Future<T | TResult> {
    return this.then(undefined, onrejected);
  }

  /**
   * 该方法为 Future 添加一个回调函数,并返回一个新的 Future。
   * 这个新的 Future 将在原 Future 被兑现时兑现。
   * 而传入的回调函数将在原 Future 被敲定(无论被兑现还是被拒绝)时被调用。
   * 
   * @param onfinally 需要添加的回调函数
   * @since ES2018
   */
  finally(onfinally?: (() => void) | undefined | null): Future<T> {
    if(typeof onfinally !== "function"){
      onfinally = () => {
        return;
      };
    }
    return this.then(
      (value)=>{
        return Future.resolve((onfinally as (() => void))()).then(
            ()=>value
          )
      },
      (reason)=>{
        return Future.resolve((onfinally as (() => void))()).then(
          ()=>{throw reason}
        )
      }
    )
  }

  /**
   * 这个方法返回一个新的 Future 对象,
   * 等到所有的 Future 对象都成功或有任意一个 Future 失败。
   * 如果所有的 Future 都成功了,
   * 它会把一个包含 iterable 里所有 Future 返回值的数组作为成功回调的返回值。
   * 顺序跟 iterable 的顺序保持一致。
   * 一旦有任意一个 iterable 里面的 Future 对象失败
   * 则立即以该 Future 对象失败的理由来拒绝这个新的 Future。
   * @param iterable
   */
  static all<T>(iterable: Iterable<Future<T>>) {
    let ct = 0;
    let length = 0;
    let arr: any[] = [];
    return new Future((resolve, reject) => {
      for (let future of iterable) {
        length = length + 1;
        future.then(
          (value: any) => {
            ct = ct + 1;
            arr[ct] = value;
          },
          (reason: any) => {
            reject(reason);
          }
        );
      }
      if (length === ct) {
        resolve(arr);
      }
    });
  }

  // /**
  //    * 创建一个Future,当所有提供的 Future 都被解析或拒绝时,该 Future 将通过一个结果数组进行解析。
  //    * @param values 一个以 Futures 为成员的数组.
  //    * @returns 一个新的 Future.
  //    * @since ES2018
  //    */
  //  allSettled<T extends readonly unknown[] | []>(values: T): Future<{ -readonly [P in keyof T]: FutureSettledResult<Awaited<T[P]>> }>;

  //  /**
  //   * 创建一个Future,当所有提供的 Future 都被 解析 或 拒绝 时,该 Future 将通过一个结果数组进行解析。
  //   * @param values 一个以 Futures 为成员的数组.
  //   * @returns 一个新的 Future.
  //   * @since ES2018
  //   */
  //  allSettled<T>(values: Iterable<T | Thenable<T>>): Future<FutureSettledResult<Awaited<T>>[]>;
  //  allSettled<T>(values: T | Iterable<T | Thenable<T>>){
  //   return new Future((resolve, reject) => {

  //   })
  //  }

  /**
   * 该方法用于获取首个兑现的 future 的值。
   * 只要有一个 future 兑现了,那么此方法就会提前结束,
   * 而不会继续等待其他的 future 全部敲定。
   *
   * 不像 future.race() 总是返回第一个敲定值(兑现或拒绝)那样,
   * 这个方法返回的是第一个兑现的值。
   * 这个方法将会 **忽略掉所有的被拒绝的 future**,
   * 直到第一个 future 兑现。
   * @param iterable
   */
  static any<T>(iterable: Iterable<Future<T>>) {
    return new Future((resolve, reject) => {
      for (let future of iterable) {
        future.then(
          // 某个 future 兑现则新 future 兑现
          (value: any) => {
            resolve(value);
          },
          // 某个 future 拒绝,不做任何处理
          (reason: any) => {}
        );
      }
    });
  }

  /**
   * 等到任意一个 Future 的状态变为已敲定。
   * 当 iterable 参数里的任意一个子 Future 成功或失败后,
   * 父 Future 马上也会用子 Future 的成功返回值或失败详情
   * 作为参数调用父 Future 绑定的相应处理函数,并返回该 Future 对象。
   * @param iterable
   */
  race<T>(iterable: Iterable<Future<T>>) {
    return new Future((resolve, reject) => {
      for (let future of iterable) {
        future.then(
          (value: any) => {
            resolve(value);
          },
          (reason: any) => {
            reject(reason);
          }
        );
      }
    });
  }

  /**
   * 创建一个新的 resolved 的 Future 实例.
   * @returns 一个状态为 resolved 的 Future 实例.
   */
  static resolve(): Future<void>;

  /**
   * 为所给定的 value 创建一个新的 resolved 状态的 Future 实例
   * @param value 一个任意 Future 实例.
   * @returns 内部状态与提供的 Future 相匹配的 Future。
   */
  static resolve<T>(value: T | Thenable<T>): Future<T>;
  static resolve<T>(value?: T | Thenable<T>) {
    return new Future((resolve, reject) => {
      if (value instanceof Future) {
        value.then(
          (vl) => {
            resolve(vl);
          },
          (rs) => {
            reject(rs);
          }
        );
      } else {
        resolve(value);
      }
    });
  }

  /**
   * 返回一个状态为已拒绝的 Future 对象,并将给定的失败信息传递给对应的处理函数。
   * @param reason 拒绝的原因
   * @returns 一个状态为已拒绝的 Future 对象
   */
  static reject(reason?: any): Future<any> {
    return new Future<any>((resolve, reject) => {
      reject(reason);
    });
  }
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。