关于javascript:手写一个跑通PromiseA的Promise

42次阅读

共计 15482 个字符,预计需要花费 39 分钟才能阅读完成。

一、引言

这周末,忽然想起小组读书打卡还有一个撸一个 Promise 的工作还没有实现,尽管我之前有试过撸一个 Promise,然而没试过应用 PromiseA+ 来测试,所以打算写一篇 wiki 来记录一下我实现的这一个过程。

二、本人写一个 Promise 须要做什么

首先,咱们要明确咱们要实现一个 Promise 须要去做什么。

1. 因为新建 Promise 要用到 new 关键字,所以咱们 须要将手动实现的 Promise 封装成一个类;

2. 因为 new Promise()的参数是一个函数,所以 手动实现的 Promise 的参数是一个函数

3. 因为传进 Promise 外面的函数 还有两个参数 resolve 函数和 reject 函数,这两个函数的作用是扭转 Promise 的状态;

4.promise 对象 有三个状态 pending, fullfilled, rejected,初始状态为 pending,调用 resolve 会将其改为 fullfilled,调用 reject 会改为 rejected,而且 Promise 对象的状态一旦产生扭转便不能再变为其余的状态,有且只有 pending 变为 fullfilled 和 pending 变为 rejected 两种可能

5.promise 实例对象 建好后能够调用 then 办法 ,而且是能够 链式调用 then 办法,阐明 then 是一个实例办法 。也就是说 调用了 then 办法之后返回的也是一个 promise 实例对象

三、分步实现

明确了咱们须要做什么,那接下来二话不说开撸。然而咱们不可能一口气吃成一个瘦子,所以咱们须要依照下面写到的步骤一步步实现。

第一步:实现根本的框架

// 先定义三个状态
const PENDING = 'pending';
const FULLFILLED = 'fullfilled';
const REJECTED = 'rejected';

class MyPromise {constructor(fn) {
          this.status = PENDING;      // 初状态为 pending
        this.value = null;          // 初始化 value
        this.reason = null;         // 初始化 reason
      
        // 定义 resolve 办法
        this.resolve = (value) => {if(this.status === PENDING) {
                this.status = FULLFILLED;
                this.value = value;
            }
        }

        // 定义 rejecte 办法
        this.reject = (reason) => {if(this.status === PENDING) {
                this.status = REJECTED;
                this.reason = reason;
            }
        }

        // 将 resolve 和 reject 作为参数调用传进来的参数,加上 try...catch,一旦产生谬误就调用 reject
        try {fn(this.resolve, this.reject);
        } catch(error) {this.reject(error);
        }

        this.then = this.then.bind(this);
    }

    then(onFullfilled, onRejected) {
        //fullfilled 状态则会调用 onFullfilled 函数
        if(this.status === FULLFILLED) {onFullfilled(this.value);
        }

        //rejected 状态则会调用 onRejected 函数
        if(this.status === REJECTED) {onRejected(this.reason);
        }
    }
}

这样,咱们根本的框架就曾经成形了,然而,then 函数那里很显著是有缺点的,试想,如果传递给 then 函数的参数 onFullfilled 和 onRejected 如果不是一个函数呢,那这样必定会报错的,所以咱们 then 函数外面增加这样的一个判断:如果传递进来的参数不是一个函数,则间接返回 value 和 reason 的 error。

then(onFullfilled, onRejected) {
    // 如果 onFulfilled 不是函数,给一个默认函数,返回 value
    let realOnFullfilled = onFullfilled;
    if(typeof realOnFullfilled !== 'function') {realOnFullfilled = (value) => value;
    }

    // 如果 onRejected 不是函数,给一个默认函数,返回 reason 的 error
    let realOnRejected = onRejected;
    if(typeof realOnRejected !== 'function') {realOnRejected = (reason) => {throw reason;}
    }

    //fullfilled 状态则会调用 onFullfilled 函数
    if(this.status === FULLFILLED) {onFullfilled(this.value);
    }

    //rejected 状态则会调用 onRejected 函数
    if(this.status === REJECTED) {onRejected(this.reason);
    }
}

第二步:明确 then 办法是什么时候执行

如果只是像下面这样写的话,如果我执行上面的代码:

new Promise(fn).then(onFulfilled, onRejected);

这时候,不论 fn 的异步操作有没有完结,then 办法都会马上执行,这显然是不合理的。咱们须要的是当 fn 外面的异步操作胜利或失败(即是 status 从 pending 变为 fullfilled 或者 rejected)之后才会去执行 then 办法。如果要实现这个先后顺序该怎么办呢?

很简略,只有咱们 限度 onFulfilled 和 onRejected 执行的机会 就能够了,那该怎么限度呢?

很显著,咱们是须要等到 status 从 pending 变为 fullfilled 或者 rejected 才会去执行onFulfilled 或 onRejected。那如果 fn 的异步操作还没有实现(即是 status 还未从 pending 变为 fullfilled 或者 rejected)怎么办?

很简略,那就 把 onFulfilled 和 onRejected 先用一个数组暂存起来呗 等到 fn 的异步操作实现 即是 status 从 pending 变为 fullfilled 或者 rejected),标记就是fn 中的 resolve 或 reject 函数执行,再去执行 onFulfilled 或者 onRejected 就行了。

好了,剖析这么多,干吧!

这个是 then 办法外面补充的:

then(onFullfilled, onRejected) {
  // 省略其余的代码
  // 如果还是 PENDING 状态,将回调保留下来
  if(this.status === PENDING) {this.onFullfilledCallbacks.push(realOnFullfilled);
    this.onRejectedCallbacks.push(realOnRejected);
  }
}

这个是在 resolve 办法和 reject 办法外面补充的:

// 定义 resolve 办法
this.resolve = (value) => {if(this.status === PENDING) {
    this.status = FULLFILLED;
    this.value = value;
    //fn 状态由 pending 变成 fullfilled,执行 then 外面的 onFullfilled 回调函数
    this.onFullfilledCallbacks.forEach(callback => {callback(this.value);
    })
  }
}

// 定义 rejecte 办法
this.reject = (reason) => {if(this.status === PENDING) {
    this.status = REJECTED;
    this.reason = reason;
    //fn 状态由 pending 变成 rejected,执行 then 外面的 onRejected 回调函数
    this.onRejectedCallbacks.forEach(callback => {callback(this.reason);
    })
  }
}

好了,咱们曾经实现下面的构想了,当初能够来测试一波:

因为应用到了 request 模块,天然是要装上的:

npm install --save-dev request

因为在这里我应用了 ES6, 然而 node 还没有齐全反对 ES6,所以这里配置了一下 package.json:

{
  "name": "test",
  "version": "","type":"module",            // 要将 type 设置为 module,node 就能够反对 ES6 而不须要装 babel"devDependencies": {"babel-register":"^6.26.0","promises-aplus-tests":"^2.1.2","request":"^2.88.2"},"scripts": {"test":"promises-aplus-tests MyPromise"},"dependencies": {"koa":"^2.13.0"        // 这个能够疏忽掉}
}

最初,在终端运行:

node MyPromiseTest.js

MyPromiseTest.js

import MyPromise from './MyPromise.js';
import request from 'request';
import babel from 'babel-register';

let promise1 = new MyPromise((resolve) => {request('https://www.baidu.com', (error, response) => {if(!error && response.statusCode === 200) {resolve('request1 success');
        }
    });
});

promise1.then((value) => console.log(value));

let promise2 = new MyPromise((resolve, reject) => {request('https://www.baidu.com', (error, response) => {if(!error && response.statusCode === 200) {reject('request2 failed');
        }
    });
});

promise2.then((value) => {console.log(value);
}, (reason) => {console.log(reason);
});

测试后果:

第一第二步测试通过,no problem!

第三步:实现 then 办法的返回值,使 then 办法可能链式调用

到这里为止,其实咱们曾经能够实现异步调用了,只是 then 的返回值还没实现,还不能实现链式调用。依据标准 then 的返回值必须是一个 promise。依据要求的不同状况,抉择分步解决。

1. 如果 onFulfilled 或者 onRejected 抛出一个异样 e,则 promise2 必须拒绝执行,并返回拒因 e。

解决办法:每次执行 onFulfilled 或者 onRejected 新建一个 promise,应用 try…catch 语句快捕捉到执行执行 onFulfilled 或者 onRejected 过程中抛出的谬误,并且应用 reject 办法解决它。

// 如果还是 PENDING 状态,也不能间接保留回调办法了,须要包一层来捕捉谬误
if(this.status === PENDING) {// this.onFullfilledCallbacks.push(realOnFullfilled);
  // this.onRejectedCallbacks.push(realOnRejected);
  let promise2 = new MyPromise((resolve, reject) => {this.onFullfilledCallbacks.push(() => {
      try {realOnFullfilled(this.value);
      } catch(error) {reject(error);
      }
    });
    this.onRejectedCallbacks.push(() => {
      try {realOnRejected(this.reason);
      } catch(error) {reject(error);
      }
    });
  });

  return promise2;
}

//fullfilled 状态则会调用 onFullfilled 函数
if(this.status === FULLFILLED) {let promise2 = new MyPromise((resolve, reject) => {
    // 这里不能简略的调用 realOnFullfilled 函数了,要应用 try...catch 语句块抱起来,如果有错就 reject
    try {realOnFullfilled(this.value);
    } catch(error) {reject(error);
    }
  });

  return promise2;
}

//rejected 状态则会调用 onRejected 函数
if(this.status === REJECTED) {let promise2 = new MyPromise((resolve, reject) => {
    // 这里不能简略的调用 realOnRejected 函数了,要应用 try...catch 语句块抱起来,如果有错就 reject
    try {realOnRejected(this.reason);
    } catch(error) {reject(error);
    }
  });

  return promise2;
}

2. 如果 onFulfilled 不是函数且 promise1 胜利执行,promise2 必须胜利执行并返回雷同的值

解决办法:判断状态为 FULLFILLED 的时候,增加一层判断,判断 onFullfilled 是不是函数。如果不是,间接 resolve, 如果是,先执行 onFullfilled 函数,再 resolve。

// 这只是一个例子,每个 onFullfilled 函数都要这样写
//fullfilled 状态则会调用 onFullfilled 函数
if(this.status === FULLFILLED) {let promise2 = new MyPromise((resolve, reject) => {
    // 这里不能简略的调用 realOnFullfilled 函数了,要应用 try...catch 语句块抱起来,如果有错就 reject
    try {
      // 加一层 onFullfilled 是不是函数的判断
      if(typeof onFullfilled !== 'function') {resolve(this.value);        // 返回雷同的值
      } else {realOnFullfilled(this.value);
        resolve(this.value);
      }
    } catch(error) {reject(error);
    }
  });

  return promise2;
}

3. 如果 onRejected 不是函数且 promise1 拒绝执行,promise2 必须拒绝执行并返回雷同的拒因。

解决办法:判断状态为 REJECTED 的时候,增加一层判断,判断 onRejected 是不是函数。如果不是,间接 reject,如果是,先执行 onRejected 函数,再 resolve。

// 这只是一个例子,每个 onRejected 函数都要这样写
//rejected 状态则会调用 onRejected 函数
if(this.status === REJECTED) {let promise2 = new MyPromise((resolve, reject) => {
    // 这里不能简略的调用 realOnRejected 函数了,要应用 try...catch 语句块抱起来,如果有错就 reject
    try {
      // 加一层 onRejected 是不是函数的判断
      if(typeof onRejected !== 'function') {reject(this.reason);
      } else {realOnRejected(this.reason);
        resolve();}
    } catch(error) {reject(error);
    }
  });

  return promise2;
}

4. 如果 onFulfilled 或者 onRejected 返回一个值 x,则运行上面的 Promise 解决过程:[[Resolve]](promise2, x)

解决办法:因为多了这一条规定,所以咱们还须要对胜利调用 onFullfilled 函数或 onRejected 函数的返回值做判断,如果有返回值就要进行 Promise 解决过程。所以咱们须要封装一个办法来进行 Promise 解决过程,暂且将这个办法命名为 resolvePromise 吧。

// 这只是一个例子,其余类似的中央也要这样写
//fullfilled 状态则会调用 onFullfilled 函数
if(this.status === FULLFILLED) {let promise2 = new MyPromise((resolve, reject) => {
    // 这里不能简略的调用 realOnFullfilled 函数了,要应用 try...catch 语句块抱起来,如果有错就 reject
    try {
      // 加一层 onFullfilled 是不是函数的判断
      if(typeof onFullfilled !== 'function') {resolve(this.value);        // 返回雷同的值
      } else {let x = realOnFullfilled(this.value);           // x 是执行 OnFullfilled 函数的返回值
        resolvePromise(promise2, x, resolve, reject);   // 调用 Promise 解决过程
      }
    } catch(error) {reject(error);
    }
  });

  return promise2;
}

第四步:Promise 解决过程

规定太多了,都放进代码外面了,这个很简略,就是依照规定实现就好了

function resolvePromise(promise, x, resolve, reject) {
    // 如果 promise 和 x 指向同一对象,以 TypeError 为拒因拒绝执行 promise
    if(promise === x) {return reject(new TypeError('The promise and the return value are the same'));
    }

    if(x instanceof MyPromise) {
        // 如果 x 为 promise,则使 promise 承受 x 的状态
        // 也就是继续执行 x,如果执行的时候拿到了一个 y,还要持续解析 y
        x.then((y) => {resolvePromise(promise, y, resolve, reject);
        }, reject);
    } else if(typeof x === 'object' || typeof x === 'function') {
        // 如果 x 为对象或函数
        if(x === null) {return resolve(x);
        }
        try {
            // 把 x.then 赋给 then
            var then = x.then;
        } catch(error) {return reject(error);
        }

        // 如果 then 是函数
        if(typeof then === 'function') {
            let called = false;         //called 示意 resolvePromise 或者 rejectPromise 被调用
            // 将 x 作为函数的作用域 this 调用
            // 传递两个回调函数作为参数,第一个参数叫做 resolvePromise,第二个参数叫做 rejectPromise
            try {
                then.call(
                    x,
                    // 如果 resolvePromise 以值 y 为参数被调用,则运行 [[Resolve]](promise, y)
                    //resolvePromise
                    (y) => {
                        // 如果 resolvePromise 和 rejectPromise 均被调用
                        // 或者同一参数被调用了屡次,则优先采纳首次调用并疏忽剩下的调用
                        if(called) return;
                        called = true;
                        resolvePromise(promise, y, resolve, reject);
                    },
                    (r) => {if(called) return;
                        called = true;
                        reject(r);
                    }
                );
            } catch(error) {
                // 如果调用 then 办法抛出了异样 e,
                // 如果 resolvePromise 或者 rejectPromise 曾经被调用,则疏忽之
                if(called) return;
                reject(error);
            }
        } else {
            // 如果 then 不是函数,以 x 为参数执行 promise
            resolve(x);
        }
    } else {
        // 如果 x 不为对象或函数,以 x 为参数执行 promise
        resolve(x);
    }
}

第五步:onFulfilled 和 onRejected 的执行机会

在标准中还有一条:onFulfilled 和 onRejected 只有在执行环境堆栈仅蕴含平台代码时才可被调用 。这一条的意思是实际中 要确保 onFulfilled 和 onRejected 办法异步执行 且应该在 then 办法被调用的那一轮事件循环之后的新执行栈中执行 。所以在 咱们执行 onFulfilled 和 onRejected 的时候都应该包到 setTimeout 外面去

增加了 setTimeout 的 then 办法:

then(onFullfilled, onRejected) {
  // 如果 onFulfilled 不是函数,给一个默认函数,返回 value
  let realOnFullfilled = onFullfilled;
  if(typeof realOnFullfilled !== 'function') {realOnFullfilled = (value) => value;
  }

  // 如果 onRejected 不是函数,给一个默认函数,返回 reason 的 error
  let realOnRejected = onRejected;
  if(typeof realOnRejected !== 'function') {realOnRejected = (reason) => {throw reason;}
  }

  // 如果还是 PENDING 状态,也不能间接保留回调办法了,须要包一层来捕捉谬误
  if(this.status === PENDING) {// this.onFullfilledCallbacks.push(realOnFullfilled);
    // this.onRejectedCallbacks.push(realOnRejected);
    let promise2 = new MyPromise((resolve, reject) => {this.onFullfilledCallbacks.push(() => {
        // 这里加 setTimeout
        setTimeout(() => {
          try {if(typeof onFullfilled !== 'function') {resolve(this.value);
            } else {let x = realOnFullfilled(this.value);
              resolvePromise(promise2, x, resolve, reject);   // 调用 Promise 解决过程
            }
          } catch(error) {reject(error);
          }
        }, 0);
      });
      this.onRejectedCallbacks.push(() => {
        // 这里加 setTimeout
        setTimeout(() => {
          try {if(typeof onRejected !== 'function') {reject(this.reason);
            } else {let x = realOnRejected(this.reason);
              resolvePromise(promise2, x, resolve, reject);   // 调用 Promise 解决过程
            }
          } catch(error) {reject(error);
          }
        }, 0);
      });
    });

    return promise2;
  }

  //fullfilled 状态则会调用 onFullfilled 函数
  if(this.status === FULLFILLED) {let promise2 = new MyPromise((resolve, reject) => {
      // 这里要增加 setTimeout,保障回调在下一轮事件循环开始的时候执行
      setTimeout(() => {
        // 这里不能简略的调用 realOnFullfilled 函数了,要应用 try...catch 语句块抱起来,如果有错就 reject
        try {
          // 加一层 onFullfilled 是不是函数的判断
          if(typeof onFullfilled !== 'function') {resolve(this.value);        // 返回雷同的值
          } else {let x = realOnFullfilled(this.value);           // x 是执行 OnFullfilled 函数的返回值
            resolvePromise(promise2, x, resolve, reject);   // 调用 Promise 解决过程
          }
        } catch(error) {reject(error);
        }
      }, 0);
    });

    return promise2;
  }

  //rejected 状态则会调用 onRejected 函数
  if(this.status === REJECTED) {let promise2 = new MyPromise((resolve, reject) => {
      // 这里要增加 setTimeout,保障回调在下一轮事件循环开始的时候执行
      setTimeout(() => {
        // 这里不能简略的调用 realOnRejected 函数了,要应用 try...catch 语句块抱起来,如果有错就 reject
        try {
          // 加一层 onRejected 是不是函数的判断
          if(typeof onRejected !== 'function') {reject(this.reason);
          } else {let x = realOnRejected(this.reason);           // x 是执行 OnRejected 函数的返回值
            resolvePromise(promise2, x, resolve, reject);   // 调用 Promise 解决过程
          }
        } catch(error) {reject(error);
        }
      }, 0);
    });

    return promise2;
  }
}

第六步:实现一个静态方法 deferred

官网对这个办法的定义如下:

  • deferred: 返回一个蕴含 {promise, resolve, reject} 的对象
  • promise 是一个处于 pending 状态的 promise
  • resolve(value) 用 value 解决下面那个 promise
  • reject(reason) 用 reason 回绝下面那个 promise

代码如下:

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

    return result;
}

四、测试

1. 先下载测试的工具:

npm install --save-dev promises-aplus-tests

2. 重新配置 package.json:

{
  "name": "test",
  "version": "",
  //"type": "module",            // 将这个删掉,因为测试应用的是 CommonJS 语法
  "devDependencies": {
    "babel-register": "^6.26.0",
    "promises-aplus-tests": "^2.1.2",
    "request": "^2.88.2"
  },
  "scripts": {"test": "promises-aplus-tests MyPromise"},
  "dependencies": {"koa": "^2.13.0"        // 这个能够疏忽掉}
}

3. 在 MyPromise.js 的文末将 MyPromise 抛出:

// 省略下面的代码
module.exports = MyPromise;

4. 运行 npm 脚本:

npm run test

5. 测试后果:

872 用例全通过!!!

五、实现 Promise 其余的办法

1.Promise.resolve()

将现有对象转为 Promise 对象 ,如果 Promise.resolve 办法的参数, 不是具备 then 办法的对象(又称 thenable 对象),则 返回一个新的 Promise 对象,且它的状态为 fulfilled。

实现代码如下:

resolve(parameter) {if(parameter instanceof MyPromise) {
    // 如果是传入的参数是 Promise 对象,则返回对象自身
    return parameter;
  }

  // 如果传入的参数不是一个 thenable 对象,则返回一个新的 promise 对象,且状态变为 fullfilled
  return new MyPromise((resolve) => {resolve(parameter);
  })
}

2.Promise.reject()

Promise.reject(reason)办法也会返回一个新的 Promise 实例,该实例的状态为 rejected

实现代码如下:

reject(reason) {
  // 返回一个新的 promise 实例,该实例的状态为 rejected
  return new MyPromise((resolve, reject) => {reject(reason);
  })
}

3.Promise.all()

该办法用于将多个 Promise 实例,包装成一个新的 Promise 实例。

const p = Promise.all([p1, p2, p3]);

Promise.all()办法承受一个数组作为参数 ,p1、p2、p3 都是 Promise 实例,如果不是, 就会先调用 Promise.resolve 办法,将参数转为 Promise 实例 ,再进一步解决。 当 p1, p2, p3 全副 resolve,大的 promise 才 resolve,有任何一个 reject,大的 promise 都 reject

实现代码如下:

all(promiseList) {return new MyPromise((resolve, reject) => {
    var count = 0;      // 用来统计 promiseList 中 promise 实例 resolve 的个数
    var length = promiseList.length;
    var result = [];    // 用来寄存 promiseList 中 resolved 的 promise 的返回值

    if(length === 0) {
      // 如果传递进来的是空数组,间接 resolve
      resolve(result);
    }

    promiseList.forEach((promise, index) => {// 将数组中的每一个元素都应用 Promise.resolve()办法变为 promise 对象
      MyPromise.resolve(promise).then((value) => {
        count++;
        result[index] = value;
        if(count === length) {
          // 只有当所有的 promise 实例都 resolve,新对象的状态才会变成 resolved,// 并且将每个 promise 胜利后的返回值组成数组传递给新的 promise 对象的回调函数
          return resolve(result);
        }
      }, (reason) => {
        // 只有有一个 promise 实例被 reject,返回的 promise 对象的状态就变为 rejected,// 且第一个被 reject 的实例对象的返回值会被传递给新的 promise 对象的回调函数
        return reject(reason);
      });
    });
  });
}

4.Promise.race()

该办法用于将多个 Promise 实例,包装成一个新的 Promise 实例。

const p = Promise.race([p1, p2, p3]);

该办法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。下面代码中,只有 p1、p2、p3 之中有一个实例率先扭转状态,p 的状态就跟着扭转 那个率先扭转的 Promise 实例的返回值,就传递给 p 的回调函数

实现代码:

race(promiseList) {return new MyPromise((resolve, reject) => {
    let length = promiseList.length;

    if(length === 0){return resolve();
    }

    promiseList.forEach((promise) => {MyPromise.resolve(promise).then((value) => {
        // 只有有一个 promise 被 resolve,返回的新的 promise 实例就被 resolve
        return resolve(value);
      }, (reason) => {
        // 只有有一个 promise 被 reject,返回的新的 promise 实例就被 reject
        return reject(reason);
      });
    });
  });
}

5.Promise.prototype.catch()

Promise.prototype.catch 办法 是.then(null, rejection)或.then(undefined, rejection)的别名,用于指定产生谬误时的回调函数。

实现代码如下:

catch(onRejected) {this.then(null, onRejected);
}

6.Promise.prototype.finally()

finally 办法用于指定 不论 Promise 对象最初状态如何,都会执行的操作。该办法是 ES2018 引入规范的。

实现代码如下:

finally(callback) {
  // 无论如何都会执行 callback,并且返回原来的值
  return this.then(value => MyPromise.resolve(callback()).then(() => value),
    reason => MyPromise.resolve(callback()).then(() => {throw reason})
  )
}

7.Promise.allSettled

该办法 承受一组 Promise 实例作为参数,包装成一个新的 Promise 实例 只有等到所有这些参数实例都返回后果,不论是 fulfilled 还是 rejected,包装实例才会完结 。该办法由 ES2020 引入。该办法返回的新的 Promise 实例, 一旦完结,状态总是 fulfilled,不会变成 rejected。状态变成 fulfilled 后,Promise 的监听函数接管到的参数是一个数组,每个成员对应一个传入 Promise.allSettled()的 Promise 实例的执行后果

实现代码:

allSettled(promiseList) {
  // 只有当所有的 promise 实例都返回后果(不论是 resolve 还是 reject)才会完结
  // 只会被 resolve,不会被 reject
  return new MyPromise((resolve, reject) => {
    var length = promiseList.length;
    var result = [];
    var count = 0;

    if(length === 0) {return resolve(result);
    }

    promiseList.forEach((promise, index) => {MyPromise.resolve(promise).then((value) => {
        count++;
        result[index] = {
          status: 'fullfilled',
          value: value
        };
        if(count === length) {return resolve(result);
        }
      }, (reason) => {
        count++;
        result[index] = {
          status: 'rejected',
          reason: reason
        };
        if(count === length) {return resolve(result);
        }
      });
    });
  });
}

8.Promise.any()

用法:

const p = Promise.any([p1, p2, p3]);

Promise.any()办法承受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只有参数实例有一个变成 fulfilled 状态,包装实例就会变成 fulfilled 状态;如果所有参数实例都变成 rejected 状态,包装实例就会变成 rejected 状态。

实现代码:

any(promiseList) {
  // 只有所有的 promise 都被 reject 时,新的 promise 对象才会被 reject
  // 一旦由 promise 被 resolve 时,新的 promise 对象就被 resolve
  return new MyPromise((resolve, reject) => {
    var length = promiseList.length;
    var count = 0;
    var result = [];

    if(length === 0) {return resolve(result);
    }

    promiseList.forEach((promise, index) => {MyPromise.resolve(promise).then((value) => {return resolve(value);
      }, (reason) => {
        count++;
        result[index] = reason;
        if(count === length) {return reject(result);
        }
      });
    });
  });
}

六、总结

写这篇货色写了一整天了,也终于实现了一个比拟残缺的 Promise,写完之后发现自己对 Promise 的理解变得更加透测,感觉很多货色还是须要看懂源码并且本人应用原生 js 实现一遍能力真正透测的了解它。因为源码过长,所以我将它推上了 GitHub,附上源码的地址:https://github.com/lugezuishuai/Promise-realization

正文完
 0