当前位置: 首页 > news >正文

all方法 手写promise_Promise 所有方法实现

前言

上次我们手写了一个 promise(不了解的可以点这里),相信大家已经对 Promise 有了深度的理解,这次我们再把 Promise 的所有相关方法都实现一下。

Promise.prototype.catch

Promise.prototype.catch = function(onRejected) {  return this.then(null, onRejected)}

catch 方法相对简单,就是调用 promise 自身的 then 方法,只传入失败的回调。因为 then 方法本身具有值的传递性,所以我们只需传入失败的回调即可,即使没有成功的回调,也会将值自动的传递下去。

Promise.prototype.finally

无论成功还是失败都会执行 finally

Promise.prototype.finally = function(onFinished) {  return this.then(val => {    onFinished()    return val  }).catch((err) => {    onFinished()    return err  })}

finally 需要注意

  1. finally 的回调没有参数
  2. promise 如果成功,则将成功的值正常传递下去,不会因 finally 而断掉,举例:
  3. promise 如果失败,同上
Promise  .resolve(1)  .finally(val => console.log(val)) // undefind  .then(val => console.log(val)) // 1Promise  .reject('error')  .finally(val => console.log(val)) // undefind  .catch(err => console.log(err)) // error

Promise.resolve

返回一个成功的 promise

Promise.resolve = function(val) {  return new Promise(resolve => {    resolve(val)  })}

emmm 一眼就懂

6972640dc8ce2b50c855da7ee150a948.png

Promise.reject

返回一个失败的 promise

Promise.reject = function(val) {  return new Promise((resolve, reject) => {    reject(val)  })}

啥也不说了。。。

b71f8fbb25dc5a6235b1f7378d69b249.png

Promise.all

返回一个 promise 实例。接受一个可迭代的对象,会等 iterable 参数内所有的 promise 都 resolved 时被 reslove,如果有一个 rejected,则此实例被 reject。

如果 iterable 没有 promise,则此实例直接被 resolve。

返回值是一个数组,数组的值按照 iterable 的迭代顺序排列。

Promise.all = function(ps) {  let resolve  let reject  const promise = new Promise((r, j) => {    resolve = r    reject = j  })  let fufilledCount = 0  let index = 0;  const ret = [];  const wrapFufilled = i => {    return val => {      fufilledCount += 1      ret[i] = val      if (fufilledCount >= index) {        resolve(ret)      }    }   }  const wrapRejected = i => {    return err => {      reject(err)    }  }  for (let p of ps) {    Promise.resolve(p).then(wrapFufilled(index), wrapRejected(index))    index += 1  }  return promise}

注意几个要点

  1. 因为接受的是一个可迭代对象(iterable),所以我们用 for of 遍历。
  2. 这里我们用 Promise.resolve() 包装一下所有的 promise。
  3. wrapFufilled 的目的是为了记录当前遍历的 index。

Promise.race

返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。

Promise.race = function(ps) {  let resolve  let reject  const promise = new Promise((r, j) => {    resolve = r    reject = j  })  for (let p of ps) {    Promise.resolve(p).then(      val => resolve(val),      err => reject(err)    )  }  return promise}

Promise.any

只要其中的一个 promise 成功,就返回那个已经成功的 promise 。如果可迭代对象中没有一个 promise 成功(即所有的 promises 都失败/拒绝),就返回一个失败的 promise 和AggregateError类型的实例,它是 Error 的一个子类,用于把单一的错误集合在一起。

本质上,这个方法和Promise.all()是相反的

Promise.any = function(ps) {  let resolve  let reject  const promise = new Promise((r, j) => {    resolve = r    reject = j  })  let errCount = 0  let pCount = 0  for (let p of ps) {    pCount += 1    Promise.resolve(p).then(      val => resolve(val),      err => {        errCount += 1        if (errCount >= pCount) {          reject(new AggregateError('All promises were rejected'))        }      }    )  }  return promise}

Promise.allSettled

返回一个在所有给定的promise都已经fulfilled或rejected后的promise,并带有一个对象数组,每个对象表示对应的promise结果。

这里举一个例子:

const promise1 = Promise.resolve(3);const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'));const promises = [promise1, promise2];Promise.allSettled(promises).  then((results) => results.forEach((result) => console.log(result)));  // 输出结果// Object { status: "fulfilled", value: 3 }// Object { status: "rejected", reason: "foo" }

具体实现:

Promise.allSettled = function(ps) {  let resolve  let reject  const promise = new Promise((r, j) => {    resolve = r    reject = j  })  let finishedCount = 0  let index = 0;  const ret = [];  const wrapFufilled = i => {    return val => {      finishedCount += 1      ret[i] = {        status: 'fufilled',        value: val      }      if (finishedCount >= index) {        resolve(ret)      }    }   }  const wrapRejected = i => {    return err => {      finishedCount += 1      ret[i] = {        status: 'rejected',        value: err      }      if (finishedCount >= index) {        resolve(ret)      }    }  }  for (let p of ps) {    Promise.resolve(p).then(wrapFufilled(index), wrapRejected(index))    index += 1  }  return promise}

最后

如果这篇文章对你有帮助的话期望得到你的点赞~~~

本人会长期发布关于原理解读方面的文章,如果想深入了解 js 原生,框架底层的话可以关注我呀~~~

相关文章:

  • Java 的单元测试
  • 以下不属于时序逻辑电路的有_学习笔记:时序电路基础
  • 【字符串处理】关于KMP算法输出的是什么代码
  • 好分数阅卷3.0_揭秘!自考阅卷的批改套路!
  • 手机沙盒隔离软件_最好别装手机杀毒软件,不仅没用反而是累赘!
  • 一个简单的注册页面
  • 主进程和子进程_Python 简明教程 26,Python 多进程编程
  • golang文件下载断点续传(下载客户端)
  • 天体运行轨迹_按彗星轨迹,太阳系中存在第二平面,有可能是彗星的“第二家园”...
  • 一个网页打开的全过程
  • 环境图配置不存在pbr_[翻译]你也可以制作的PBR!
  • 单引号和双引号的区别
  • 前端缓动画为什么不能有小数_前端兼容性的一些问题
  • luogu4187 [USACO18JAN]Stamp Painting (dp)
  • jsencrypt vue使用_在VUE中使用RSA加密解密加签解签__Vue.js
  • 《微软的软件测试之道》成书始末、出版宣告、补充致谢名单及相关信息
  • 【译】理解JavaScript:new 关键字
  • Cookie 在前端中的实践
  • CoolViewPager:即刻刷新,自定义边缘效果颜色,双向自动循环,内置垂直切换效果,想要的都在这里...
  • CSS盒模型深入
  • Cumulo 的 ClojureScript 模块已经成型
  • ES6系列(二)变量的解构赋值
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • MySQL用户中的%到底包不包括localhost?
  • Objective-C 中关联引用的概念
  • PAT A1017 优先队列
  • PermissionScope Swift4 兼容问题
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • 初探 Vue 生命周期和钩子函数
  • 订阅Forge Viewer所有的事件
  • 关于使用markdown的方法(引自CSDN教程)
  • 解析带emoji和链接的聊天系统消息
  • 批量截取pdf文件
  • 使用putty远程连接linux
  • 一个项目push到多个远程Git仓库
  • 由插件封装引出的一丢丢思考
  • 怎么将电脑中的声音录制成WAV格式
  • const的用法,特别是用在函数前面与后面的区别
  • 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ...
  • ​520就是要宠粉,你的心头书我买单
  • # 睡眠3秒_床上这样睡觉的人,睡眠质量多半不好
  • #多叉树深度遍历_结合深度学习的视频编码方法--帧内预测
  • #我与Java虚拟机的故事#连载01:人在JVM,身不由己
  • (JS基础)String 类型
  • (初研) Sentence-embedding fine-tune notebook
  • (附源码)计算机毕业设计SSM疫情居家隔离服务系统
  • (六)库存超卖案例实战——使用mysql分布式锁解决“超卖”问题
  • (论文阅读40-45)图像描述1
  • (一)基于IDEA的JAVA基础10
  • (转)机器学习的数学基础(1)--Dirichlet分布
  • (转)淘淘商城系列——使用Spring来管理Redis单机版和集群版
  • (转)我也是一只IT小小鸟
  • (转载)Linux 多线程条件变量同步
  • .NET 6 Mysql Canal (CDC 增量同步,捕获变更数据) 案例版
  • .Net 8.0 新的变化