前言
这里呢是我写的全部promise源码,包含以下功能1、promise核心函数 2、promise核心函数resolve() 3、promise核心函数reject()4、then方法链式调用 5、promise.reject() 6、promise.resolve()7、promise.finally() 8、promise.race() 9、promise.all()//其实还有promise.any(), promise.try(),promise.allSettled()//这三个API我没有写大家有兴趣的话可以去阮一峰的ES6入门
代码
//设置promise 状态
const PENDING = "pending"; //等待状态
const FULFILLED = 'fulfilled'; //成功状态
const REJECTED = 'rejected'; //失败状态class MyPromise {constructor(executor) {//立即调用函数try {//用于捕获错误信息executor(this.resolve, this.reject)} catch (error) {//调用reject传递错误信息this.reject(error)}}//初始化状态status = PENDING//初始化成功之后的值 用于保存结果success = undefined//初始化失败之后的值 用于保存结果error = undefined//用于保存成功回调,成功回调的默认值需要改成数组,因为只有数组可以存储多个回调函数successCallback = []//用于保存失败回调,失败回调的默认值需要改成数组,因为只有数组可以存储多个回调函数failCallback = []resolve = success => {//如果状态不是等待 则阻止程序执行if (this.status !== PENDING) return//把promise状态改为成功this.status = FULFILLED//保存成功之后的值this.success = success//这里使用while语句用successCallback.length作为循环条件,//如果数组中有值,拿到数组中的第一个回调函数传值并执行while (this.successCallback.length) this.successCallback.shift()();}reject = error => {//如果状态不是等待 则阻止程序执行if (this.status !== PENDING) return//把promise状态改为失败this.status = REJECTED//保存失败之后的值this.error = error//重新编写逻辑//这里使用while语句用failCallback.length作为循环条件,//拿到数组中的第一个回调函数传值并执行while (this.failCallback.length) this.failCallback.shift()();}static all(array) {//准备一个空数组 用于接收值let result = []//定义一个值用于和result进行对比let index = 0;//返回一个promisereturn new MyPromise((resolve, reject) => {//定义一个函数,传递两个参数//function addDate(key, value) {//key作为数组result的下标为key,值为valueresult[key] = value;//每添加一个值 index就+1index++//逻辑判断如果index === 数组的长度,就意味着所有的同步的和异步都已经执行完了if (index === result.length) {//调用resolve函数resolve(result)}}//遍历数组中所有的值for (let i = 0; i < array.length; i++) {//接收数组中的值const element = array[i];//逻辑判断 是否为promise对象if (element instanceof MyPromise) {//promise对象 成功就调用addDate函数,失败就调用reject函数element.then(success => addDate(i, success), error => reject(error))} else {//如果是普通值直接调用addDate函数addDate(i, array[i])}}})}static race(array) {return new MyPromise((resolve, reject) => {//遍历数组for (let i = 0; i < array.length; i++) {//保存单个值const current = array[i];//逻辑判断当前值是一个对象或者是当前值是一个functionif ((typeof current === 'object' && current !== null) || typeof current == 'function') {//保存当前的then方法let then = current.then;if (typeof then == 'function') { // 比较哪个promise比较快,谁快用快//改变this指向then.call(current, resolve, reject)} else {//直接调用resolve方法resolve(current);}} else {//直接调用resolve方法resolve(current);}}});}//定义静态方法static resolve(value) {//逻辑判断如果是 promise对象就返回promise对象if (value instanceof MyPromise) value//如果不是promise对象 手动返回promise对象并且把value传递进去return new MyPromise((resolve, reject) => {resolve(value)})}//定义静态方法static reject(value) {//逻辑判断如果是 promise对象就返回promise对象if (value instanceof MyPromise) return value//如果不是promise对象 手动返回promise对象并且把value传递进去return new MyPromise((resolve, reject) => {reject(value)})}then(successCallback, failCallback) {//逻辑判断successCallback是否存在,如果不存在就传递一个函数进去successCallback = successCallback ? successCallback : success => success//逻辑判断successCallback是否存在,如果不存在就传递一个函数进去并且把错误信息抛出failCallback = failCallback ? failCallback : error => { throw error }//要实现then方法的链式调用必须创建一promise对象//新建一个promise对象let promise2 = new MyPromise((resolve, reject) => {//逻辑判断如果当前状态为成功 则执行成功的回调并且把保存成功的值传递进去if (this.status === FULFILLED) {//此处仅仅将代码作为异步代码,延迟时间为0, //因为promise2 是在new MyPromise执行完成之后才能看到 在new MyPromise执行过程中是看不到的//所以将代码变成异步代码setTimeout(() => {//捕获成功函数的错误信息try {//保存上一个函数的返回值let x = successCallback(this.success)//并且把返回值传递给下一个then方法// resolve(x);//判断X的值是普通值还是promise对象//如果是普通值 直接调用resolve//如果是promise对象 查看promise对象返回的结果//再根据promise对象返回的结果 调用resolve还reject //所有同步代码执行完了才能看到promise2 resolvePromise(promise2, x, resolve, reject)} catch (error) {//手动调用reject方法 把错误信息传递给下一个promise函数reject(error)}}, 0);//逻辑判断如果当前状态为成功 则执行失败的回调并且把失败的原因传递进去} else if (this.status === REJECTED) {setTimeout(() => {//捕获错误函数的错误信息try {//保存上一个函数的返回值let x = failCallback(this.error)//并且把返回值传递给下一个then方法// resolve(x);//判断X的值是普通值还是promise对象//如果是普通值 直接调用resolve//如果是promise对象 查看promise对象返回的结果//再根据promise对象返回的结果 调用resolve还reject //所有同步代码执行完了才能看到promise2 resolvePromise(promise2, x, resolve, reject)} catch (error) {//手动调用reject方法 把错误信息传递给下一个promise函数reject(error)}}, 0);} else {//当前状态为等待,也就是promise状态为pending,//如果是等待的话那应该调用成功回调还是失败回调呢//那当然是两个回调都无法调用,应为不知道到底是成功了还是还是失败了//在这种情况下应该将成功回调和失败回调进行保存//保存成功回调函数//在这里有一个问题  this.successCallback一次只能存储一个函数这样的不符合要求//所以在上面定义successCallback的时候将其定义为数组,这样就可以存储多个回调 ,将回调push进去//重新编辑逻辑this.successCallback.push(() => {setTimeout(() => {//捕获成功函数的错误信息try {//保存上一个函数的返回值let x = successCallback(this.success)//并且把返回值传递给下一个then方法// resolve(x);//判断X的值是普通值还是promise对象//如果是普通值 直接调用resolve//如果是promise对象 查看promise对象返回的结果//再根据promise对象返回的结果 调用resolve还reject //所有同步代码执行完了才能看到promise2 resolvePromise(promise2, x, resolve, reject)} catch (error) {//手动调用reject方法 把错误信息传递给下一个promise函数reject(error)}}, 0);});//重新编辑逻辑this.failCallback.push(() => {setTimeout(() => {//捕获错误函数的错误信息try {//保存上一个函数的返回值let x = failCallback(this.error)//并且把返回值传递给下一个then方法// resolve(x);//判断X的值是普通值还是promise对象//如果是普通值 直接调用resolve//如果是promise对象 查看promise对象返回的结果//再根据promise对象返回的结果 调用resolve还reject //所有同步代码执行完了才能看到promise2 resolvePromise(promise2, x, resolve, reject)} catch (error) {//手动调用reject方法 把错误信息传递给下一个promise函数reject(error)}}, 0);});}})//返回promise对象return promise2}//捕捉方法catch (failCallback) {//处理失败的回调,第一个回调为undefinedreturn this.then(undefined, error => failCallback(error))} finally(callback) {//通过this.then拿到当前promise对象的状态return this.then(success => {//返回一个promise对象,并且执行callback,最后把success返回return MyPromise.resolve(callback()).then(() => success)},error => {//返回一个promise对象,并且执行callback,最后把捕获的错误返回return MyPromise.resolve(callback()).then(() => { throw error })})}
}
//定义函数用于判断返回的是普通值还是promise对象
function resolvePromise(promise2, x, resolve, reject) {//逻辑判断是返回的是当前的promise对象 如果是抛出错误并且阻止程序执行if (promise2 === x) {return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))}//逻辑判断如果是promise对象if (x instanceof MyPromise) {//如果是成功的回调 就把值传递进去 失败的话就把失败的原因传递进去//  x.then(success => resolve(success), error => reject(error))//下面是简写写法x.then(resolve, reject)} else {//逻辑判断是普通值直接传递进去resolve(x)}}
//遵循commjs规范 导出
module.exports = MyPromise;

谢谢观看,如有不足,敬请指教

手写Promise-最终篇相关推荐

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

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

  2. 手写promise核心功能

    手写promise 源码地址:https://github.com/CONOR007/Handwriting-Promise.git 手写promise首先需要掌握promise的基本用法,然后根据用 ...

  3. javascript --- 手写Promise、快排、冒泡、单例模式+观察者模式

    手写promise 一种异步的解决方案, 参考 Promise代码基本结构 function Promise(executor){this.state = 'pending';this.value = ...

  4. 一个下课的时间带你手写promise!

    要手写前先看看用法,用法就是我们的需求 //直接调用 let promise=new Promise((resolve,reject)=>{resolve('123') }) promise.t ...

  5. 手写 Promise

    手写 Promise 实现一个简易版 Promise 在完成符合 Promise/A+ 规范的代码之前,我们可以先来实现一个简易版 Promise,因为在面试中,如果你能实现出一个简易版的 Promi ...

  6. 面试必备--手写Promise.all与.race

    最近面试被问到了手写Promise .all 与 Promise.race,奈何没有自己实现过,只能阿巴阿巴 面完之后,冷静下来思考了该如何实现,并把他写了下来(在实现过程中确实收获不少,让我对这两个 ...

  7. 【Promise】自定义 - 手写Promise - Promise.all - Promise(executor)

    手写Promise 1. 整体结构框架 2. Promise(executor) 3. Promise.prototype.then 4. Promise.prototype.catch 5. Pro ...

  8. c0语言 测试用例,按照 Promise/A+ 手写Promise,通过promises-aplus-tests的全部872个测试用例...

    本文主要讲述如何根据 Promises/A+ 规范,一步步手写一个 Promise 的 polyfill,代码中会配上对应的规范解释. 1. 定义需要的常量和工具方法// 1. 定义表示promsie ...

  9. 【学习笔记】Part1·JavaScript·深度剖析-函数式编程与 JS 异步编程、手写 Promise(二、JavaScript 异步编程)

    [学习笔记]Part1·JavaScript·深度剖析-函数式编程与 JS 异步编程.手写 Promise(课前准备) [学习笔记]Part1·JavaScript·深度剖析-函数式编程与 JS 异步 ...

  10. 手写Promise和all、race等方法,附上原理解析

    手写一个迷你版的Promise JavaScript 中的 Promise 诞生于 ES2015(ES6),是当下前端开发中特别流行的一种异步操作解决方案,简单实现一个迷你版本帮助深入理解 Promi ...

最新文章

  1. mysql 导出dmp文件_Mysql数据库的各种命令:
  2. Android下HelloWorld项目的R.java文件介绍
  3. 我的Go+语言初体验--Go+之环境安装与程序编码初体验
  4. 输出国际象棋输出余弦曲线
  5. SQL Server 2005: Constraints
  6. 实验一 命令解释程序的编写
  7. 不用加号实现两整数相加
  8. 类和对象编程(四):拷贝构造函数
  9. 第4代计算机的cpu,世界最小电脑进化第四代:继续用APU
  10. 浅谈C语言字符串结束符'\0'
  11. android电视不能root权限,有谁知道安卓电视root权限获取方法?
  12. Hive的概述、流程和优化
  13. 微信头像卡片制作,听说很火?
  14. css中关于旋转属性trtransform: rotate影响文字轻微变形的解决办法。
  15. wireshark 过滤omci包_中兴OLT、ONU常见故障问题处理
  16. VIJOS 1206 CoVH之再破难关
  17. P4094 [HEOI2016/TJOI2016]字符串 [SA + 主席树]
  18. 软件项目管理——文档
  19. 【图解】Web前端实现类似Excel的电子表格
  20. IE浏览器十大进化史 盘点微软IE1到IE10辉煌历程(转)

热门文章

  1. Linux正则表达式基本使用
  2. python getattribute方法_Python:避免getattribute中的无限循环__
  3. Android-设计模式
  4. 漏洞修复:HTML5: Overly Permissive CORS Policy
  5. Microsoft Defender防病毒扫描添加排除项
  6. java 实现自动生成部署文档_jenkins的部署、实现自动拉取gitlab仓库代码、实现项目中代码自动部署以及项目关联触发......
  7. linux系统查询二进制BIn文件方法
  8. WebLogic 配置JNDI数据源
  9. [数理统计] 分布族谱图
  10. 基于echarts制作的洛阳市3D地图