一般 Node 教科书对 Promise 基本用法的描述是:

    1. const promiseObj = new Promise(function (resolve, reject) {
    2. // ... some code
    3. if (/* 异步操作成功 */) {
    4. resolve(value);
    5. } else {
    6. reject(error);
    7. }
    8. });

    为 Promise 的 constructor 传入一个 executor 函数,在其中有两个改变状态的函数 resolve/reject(也可以不叫这两个名字),在这个 executor 中做完异步操作后,使用 resolve/reject 来改变当前创建的这个 promiseObj 的状态。

    但是,「做**异步操作」和「改变 promiseObj **状态」这两件事,都可以不必限制在传给 Promise constructor 的这个 executor 中去做!两件事情,都完全可以在其它地方(如其它的函数、类、package)去做!

    而要实现这样的灵活性,其要点就在于把这个 executor 的 resolve/reject 函数给返回出来。此时,executor 本身只需要做一件事:将 resolve/reject 赋值到外部去,即:将 resolve/reject 做成 closure 返回到外部去。

    1. let resolveRef, rejectRef;
    2. const promiseObj = new Promise(function (resolve, reject) {
    3. resolveRef = resolve;
    4. rejectRef = reject;
    5. });
    6. // ....
    7. await promiseObj;
    8. // ... do async operations at other function/class/package...
    9. // ... and after done, call the resolveRef/rejectRef change promiseObj state.

    此时,阻塞的地方可以依旧可以直接 await 这个 promiseObj,而异步操作可以在任何其他地方(其它的函数、类、package)去做。只要将上面返回到外部的、promiseObj 的 resolve/reject,传递到这个「其他地方」,在它完成自己的异步操作后,直接执行接收到的 resolve/reject 来改变 promiseObj 状态即可。

    可以看到 promiseObj 本身其实是没有 resolve/reject 方法的。Promise constructor 接收到的是一个 executor,而这个executor 的定义是:

    • executor 本身是一个函数。
    • 这个函数的第一个参数也是一个函数,在「定义处」称之为 resolve。
    • 这个函数的第二个参数也是一个函数,在「定义处」称之为 reject。
    • Promise 内部是根据这个 executor 的 parameter 定义来做状态的改变,但最后创建出来的实例,并不知晓有方法叫做 resolve/reject。因为这个两个方法是依赖于 executor 而定义的,而不是依赖于 Promise 本身而定义的。

    所以,要拿到这个 executor 的 resolve/reject 方法,就只能在定义 executor 的时候获取。也即是上面所说的通过外部定义的 resolveRef, rejectRef 在定义出将它们返回出来。

    一旦外部获得了 executor 的 resolve/reject 方法,那么关于这个 promise 的异步执行函数、以及执行完成后对这个 promise 状态的改变,都可以非常灵活地在其它地方发生了。