前言
本文将带你完成以下任务,相信你会更好掌握 Promise。
- JS实现一个带并发限制的异步调度器Scheduler,保证同时运行的任务最多有两个
- 实现Promise.all
- 实现Promise.any
- 实现Promise.race
- Promise.allSettled
- 多个返回promise的函数串行执行
- Promise 超时设计,利用Promise.race来实现
第一题
JS实现一个带并发限制的异步调度器Scheduler,保证同时运行的任务最多有两个。
完整题目
答案
解释
- 当前执行并发大于等于2时,生成一个暂停的Promise,把resolve添到一个数组中,下面的代码被暂停执行
- 当前执行并发小于2, 立即执行异步操作并在该异步操作执行完毕后从数组中弹出最先push的resolve改变Promise的状态
- 由于Promise被resolve了,最初被暂停的代码可以继续执行
- 关键点为 Promise 没有被 resolve 或 reject 时后面代码会被暂停,Promise 的 resolve 或 reject 可以在Promise构造函数外执行
解释非常好的文章
第二题
实现Promise.all()
// 结束条件:有一个 Promise rejected 或 所有 Promise resolved。
- 接收一个 Promise 实例的数组或具有 Iterator 接口的对象
- 如果元素不是 Promise 对象,则使用 Promise.resolve 转成 Promise 对象
- 如果全部成功,状态变为 resolved,返回值将组成一个数组传给回调
- 只要有一个失败,状态就变为 rejected,返回值将直接传递给回调all() 的返回值也是新的 Promise 对象
- 注意⚠️,不管是Promise.all、any、race还是allSettled,参数都是一个🉑️迭代对象及部署了[Symbol.iterator]方法(如array\string\map\set\有length属性的对象)123456789101112131415161718192021222324function promiseAll(iterable) {let array = Array.from(iterable);let resolveNum = 0;let promiseNum = array.length;let lists = new Array(promiseNum);return new Promise((resolve, reject) => {for (let i = 0; i < promiseNum; i++) {Promise.resolve(array[i]).then(res => {lists[i] = res;resolveNum++;if (resolveNum === promiseNum) {return resolve(lists)}}).catch(reason => {return reject(reason);});}});}// promiseAll([1, Promise.reject(12)]).then(res => {// console.log(res)// }).catch(reason => {// console.log(reason)// });
第三题
实现Promise.any()
- 结束条件:有一个 Promise resolved 或 所有 Promise rejected 就返回一个AggregateError类型的实例。
- 如果可迭代对象中没有一个 promise 成功(即所有的 promises 都拒绝),就返回一个失败的 promise 和AggregateError类型的实例,它是 Error 的一个子类,用于把单一的错误集合在一起。
这里你有学习到了一个新的错误类型 AggregateError 快去看看吧1234567891011121314151617181920212223242526272829function promiseAny(iterable) {let array = Array.from(iterable);let promiseNum = array.length;let rejectNum = 0;return new Promise((resolve, reject) => {for (let i = 0; i < promiseNum; i++) {Promise.resolve(array[i]).then(res => {return resolve(res);}).catch(error => {rejectNum++;if (rejectNum === promiseNum) {return reject(new AggregateError("", "All promises were rejected"))}});}});}// var p1 = new Promise(function (resolve, reject) {// setTimeout(reject, 500, "one");// });// var p2 = new Promise(function (resolve, reject) {// setTimeout(reject, 600, "two");// });// promiseAny([p1, p2]).then(res => {// console.log(res)// }).catch(error => {// console.log(error)// });
第四题
实现Promise.race()
结束条件:一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。
第五题
Promise.allSettled()
- 结束条件:所有给定的promise都已经fulfilled或rejected后的promise。
- 对于 promise 为 resolved 时对象为 {status: ‘fulfilled’, value: promise的值}
- 对于 promise 为 rejected 时对象为 {status: ‘rejected’, reason: rejected的原因}
目前是用在我们SSR项目中,一次性会在服务端发起多个请求,总不能一个请求挂掉都把成功的请求都丢弃吧,你可是试试这个方法。
第六题
多个返回promise的函数串行执行
第七题
Promise 超时设计,利用Promise.race来实现
最后
行文匆忙(主要是要哄👶睡觉了),本文主要是个人对 Promise 的一些理解,如有错误还望斧正。