离上次写了 Promise.all 实现之后,已经隔了,呃,快一年了...

为什么又想起来写 Promise 的其他静态方法的实现呢?原因是最近已经连续两次收到了某跳动公司的面试邀请了。想着虽然不一定去面,但还是要把一些面试的八股文给熟悉一下,毕竟又写了快一年的业务代码了,自己的长进也是模模糊糊,好像也没有落到具体的东西上...

首先我们先回顾下 Promise.all 静态方法的实现

rencoo:[面试题]实现Promise.all​zhuanlan.zhihu.com

记得当时写完之后,知乎上有个哥们 Rambo 还热心地指出我的问题,并且他自己也写了更加完美的实现

Rambo:Promise.all实现​zhuanlan.zhihu.com


接下来呢,我们就来看看现在要实现的 Promise.allSettled 静态方法

还是从它的用法入手:

相对于 Promise.all 需要所有 promise都成功时才 resolve或者有一个失败时即reject,Promise.allSettled 只关心所有 promise 是不是都被 settle 了,不管其是 rejected状态的 promise,还是非 rejected状态(即fulfilled)的 promise, 我都可以拿到它的最终状态并对其进行处理

Promise.allSettled 的结果数组中可能包含以下两种格式的数据

  • {status:"fulfilled", value:result} 对于成功的响应
  • {status:"rejected", reason:error} 对于 error

参照原理写的 Promise.all 的实现,我们根据 Promise.allSettled 的概念,稍作改变就可以写出实现

if (!Promise.allSettled) {Promise.allSettled = function (promises) {return new Promise(resolve => {const data = [], len = promises.length;let count = len;for (let i = 0; i < len; i += 1) {const promise = promises[i];promise.then(res => {data[i] = { status: 'fulfilled', value: res };}, error => {data[i] = { status: 'rejected', reason: error };}).finally(() => { // promise has been settledif (!--count) {resolve(data);}});}});}
}

测试下

const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'));
const promises = [promise2, promise1];Promise.allSettled(promises).then((results) => results.forEach((result) => console.log(result.status)));// expected output:
// "rejected"
// "fulfilled"


另外,更加简便的,我们也可以根据 Promise.all 来实现 Promise.allSettled

思路是让 Promise.all 入参中的所有 promise 都映射为新的最终状态为 fulfilled 的 promise (而新promise的result则根据原来promise的状态为fulfilled/reject来决定),这样就总是能让Promise.all 成功返回数组

if (!Promise.allSettled) {Promise.allSettled = function (promises) {return Promise.all(promises.map(p => Promise.resolve(p).then(res => {return { status: 'fulfilled', value: res }}, error => {return { status: 'rejected', reason: error }})));};
}


最后,再对之前 Promise.all 的实现做个修正!!! 当时的实现有误,对所有 promise 是否都被 settled 的判断是错误的,不能用结果的长度来判断。把原来的那几个测试 promise 顺序一颠倒就能看出问题来了,最后一个最快被 settled,按照长度来判定的话就 resolve 出去了,但这样是不对的,因为最后的那个 promise 最快 settled 时,前面几个慢的还没有被 settled,这时候时不能 resolve 最终结果的

function all(promises) {let len = promises.length, res = []// 修正let count = lenif (len) {return new Promise(function (resolve, reject) {for(let i=0; i<len; i++) {let promise = promises[i];promise.then(response => {res[i] = response// 当返回结果为最后一个时// 修正// if (res.length === len) {if (!--count) {resolve(res)}}, error => {reject(error)})}})}
}// test
let p1 = new Promise(function (resolve, reject) {setTimeout(function () {resolve(1)// reject(new Error('error 1'))}, 3000)
})let p2 = new Promise(function (resolve, reject) {setTimeout(function () {resolve(2)}, 2000)
})let p3 = new Promise(function (resolve, reject) {setTimeout(function () {resolve(3)}, 1000)
})all([p1, p2, p3]).then(res => {console.log(res) //(*)
}).catch(console.log)
// 修正前*处
// console:[empty × 2, 3]
// 修正后*处
// console: [1, 2, 3]

最后想说的是,技术是件严谨的事情,我们需要对自己的输出有责任心,捂脸...

all方法 手写promise_实现Promise.allSettled相关推荐

  1. 方法 手写promise_手写Promise类

    手写简单promise 1.分析promise核心逻辑 先看一段代码 let p = new Promise(); //说明Promise是一个类(class),需要new实例化 let p = ne ...

  2. 方法 手写promise_高级前端养成37js专精06之手写promise(上)

    面试答题万金油方法论顺序(高级前端面试套路) 该技术要解决什么问题-why 该技术是怎么解决它的-how 该技术有什么优点(对比其他技术) - pros 该技术有什么缺点-cons 如何解决这些缺点- ...

  3. 方法 手写promise_实现一个符合 Promise/A+规范的 Promise(typescript 版)

    (给前端大全加星标,提升前端技能) 转自:Col0ring juejin.cn/post/6886360224308035598 写在前面 没错,这又是一篇关于手写 Promise 的文章,想必大家已 ...

  4. all方法 手写promise_前端进阶高薪必看手写源码篇

    前言 此系列作为笔者之前发过的前端高频面试整理的补充 会比较偏向中高前端面试问题 当然大家都是从新手一路走过来的 感兴趣的朋友们都可以看哈 初衷 我相信不少同学面试的时候最怕的一个环节就是手写代码 大 ...

  5. all方法 手写promise_我团队的一年前端实现Promise所有方法

    从零手写Promise完整版 随着前端技术的不断发展,用户对界面的要求也在不断提高,现在的前端不再是之前的html+css, 而是html+css+js,但是想学好js首先要知道js的核心在于异步,说 ...

  6. all方法 手写promise_试题-手写实现一个 promise.all - 拿OFFER

    Promise.all的实现和原理 Promise.all 功能: Promise.all(iterable)返回一个新的Promise实例,此实例在iterable参数内素有的Promise都ful ...

  7. 手写简单版 Promise

    Promise作为ES6新增的函数,帮助我们解决了回调地狱的难题,让我们的异步代码可以更加清晰简洁,作为一名前端程序员,手写简单版Promise应该是必备的技能.接下来不多说,直接上代码了. clas ...

  8. 方法 手写promise_JS探索-手写Promise

    无意间在知乎上刷到Monad这个概念,去了解了一下,前端的Promise就是一种Monad模式,所以试着学习一下手写一个Promise. 本文内容主要参考于 只会用?一起来手写一个合乎规范的Promi ...

  9. 从零开始,手写完整的Promise原理!

    珠峰十年深度沉淀,最具诚意与深度的课程限时免费开放,带你从0到1完美诠释异步编程,并手写一个完整的promise原理!  [扫码免费参加,限200人] (名额有限,扫描上方二维码立即参加!) 历史学员 ...

最新文章

  1. C语言字符串大小写转换_只愿与一人十指紧扣_新浪博客
  2. [Asp.net]绝对路径和相对路径
  3. 实验三——vlan间路由
  4. ubuntu使用redis和宝塔面板
  5. linux vi 内存,Vi Linux内存 之 Slub分配器(四)
  6. NameNode高可用中editlog同步的过程
  7. Xcode 7.3 解决自定义类无法自动联想
  8. Android平台ROM的定制及精简教程
  9. 《老罗Android开发视频教程》
  10. 关于vc隐藏浏览器控件 2010-9-7 16:07
  11. 点云 3D 目标跟踪 - AB3DMOT(IROS 2020, ECCVW 2020)
  12. 阿里云服务器,腾讯云服务器,华为云服务器被攻击了怎么办?
  13. 数据加密 RSA非对称加密篇
  14. JSP+Servlet+Mysqll银行柜员业务绩效考核系统的设计与实现(附论文)
  15. EasyExcel实现下载Excel(解决无法从浏览器下载问题)
  16. GSMA启用包容性技术实验室
  17. 资料 | 美图区域链白皮书(附PDF链接)
  18. java虚拟机最新安卓版apk
  19. 《奇点临近》奇点和纪元
  20. 计算机网络布线实训,计算机网络--综合布线实训报告.doc

热门文章

  1. 入门训练 A+B问题 c语言
  2. 在jupyter界面误删了jupyter notebook
  3. 数值分箱与one-hot
  4. 置信学习:让样本中的“脏数据“原形毕露
  5. 风控特征:时间滑窗统计特征体系
  6. ES6 generator
  7. 全视曲面屏设计,三星S8又一次走在了行业创新的最前沿
  8. 【JS】 JS毫秒值转化为正常格式 或者正常格式转化为毫秒值
  9. JavaBean fields TO ExtjsMode fields
  10. Eclipse - CDT使用GDB调试C++的问题-无源文件命名(No source file named)