一步步实现 Promises/A+ 规范 – 系列

catch 实现

上一篇文章实现了 Promises/A+ 规范中对 then 方法的要求,实现了 then 链的调用逻辑。本篇文章将实现 catch 方法、all 方法、resolve 方法、reject 方法

then 链的缺失参数调用

首先验证如下代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
new Promise((resolve, reject) => {
  resolve("success");
}).then(
  res => res + ' (promise res)',
).then(
  null, // 未传成功回调
  err => err + ' (self then err)',
).then(
  res => console.log(res),
  err => console.log(err)
)
// 输出
// success (promise res)

由此看出不传参数不影响后续调用,且把之前的结果传递给后续方法。修改 then 方法如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
then(onFulfilled, onRejected) {
  return new Promise((resolve, reject) => {
    // onFulfilled 不是 function 时设置默认方法
    if (typeof onFulfilled !== "function") {
      onFulfilled = res => res;
    }
    this.onFulfilledCallbacks.push(() => {
      try {
        const res = onFulfilled(this.value);
        if (res instanceof Promise) {
          res.then(resolve, reject);
        } else {
          resolve(res);
        }
      } catch (error) {
        reject(error);
      }
    });
    // onRejected 不是 function 时设置默认方法
    if (typeof onRejected !== "function") {
      onRejected = err => {
        throw new Error(err instanceof Error ? err.message : err);
      };
    }
    this.onRejectedCallbacks.push(() => {
      try {
        const res = onRejected(this.reason);
        if (res instanceof Promise) {
          res.then(resolve, reject);
        } else {
          resolve(res);
        }
      } catch (error) {
        reject(error);
      }
    });
  })
}

catch 实现原理

catch 的实现其实就是 then 方法没有传第一个参数,只传了第二个参数,这也就是为什么需要先实现上边的逻辑。具体实现:

1
2
3
catch(onRejected) {
  return this.then(null, onRejected);
}

Promise.all() 实现

  • Promise.all 接收一个 promise 对象的数组作为参数
  • 当这个数组里的所有 promise 对象全部变为 resolve,则执行 then 中的 onFulfilled
    • onFulfilled 方法接收一个数组作为参数,这个数组即 promise 对象数组的所有结果,顺序保持一致
  • 有一个变为 reject ,则执行 then 中的 onRejected

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    
    // 验证代码一
    const promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
    resolve(100);
    }, 1000)
    })
    const promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
    resolve(200);
    }, 500)
    })
    Promise.all([promise1, promise2]).then(
    res => console.log(res)
    )
    // 输出 [ 100, 200 ] 顺序与传入相同
    // -----------------
    // 验证代码二
    const promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
    resolve(100);
    }, 1000)
    })
    const promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
    reject(200);
    }, 500)
    })
    Promise.all([promise1, promise2]).then(
    res => console.log(res),
    err => console.log(err)
    )
    // 输出 200
    

返回一个 promise

all 方法需要和 then 方法一样返回一个 promise,但 all 方法属于类中的静态方法,其调用方式是直接通过类来调用:Promise.all(),代码实现

1
2
3
4
static all(promiseAry = []) {
  return new Promise((resolve, reject) => {
  })
}

返回一个 prmise 后,该方法就可以链式调用

监控所有 promise 执行状态

每一个 promise 实例的状态可以通过添加 then 方法进行判断,实现如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
static all(promiseAry = []) {
  return new Promise((resolve, reject) => {
    // 记录 promise 完成个数
    let finishNum = 0;
    // 返回结果
    let result = [];
    const len = promiseAry.length;
    for (let i = 0; i < len; i++) {
      // 对每一个 promise 实例增加 then 方法,监控状态
      promiseAry[i].then(val => {
        finishNum++;
        result[i] = val; // 保证结果与传入顺序一致
        if (finishNum === len) {
          resolve(result);
        }
      }, reject)
    }
  })
}

Promise.resolve() 实现

1
2
3
4
5
static resolve(arg) {
  return new Promise(function(resolve){
    resolve(arg);
  });
}

Promise.reject() 实现

1
2
3
4
5
static reject(arg) {
  return new Promise(function(resolve, reject){
    reject(arg);
  });
}

到此,就实现了 Promise/A+ 规范,可查看源码