一,整体结构

采用es5的语法来写:

//es5里面自定义模块,用的是IIFE(函数自调用)
(function(window){//定义promise构造函数//参数是excutor函数:同步执行function Promise(excutor){}// Promise原型对象的then方法,两个参数是回调函数(成功和失败),返回一个新的promise对象Promise.prototype.then=function (onResolved,onRejected){}// Promise原型对象的catch方法,一个参数是回调函数(失败),返回一个新的promise对象Promise.prototype.catch=function (onRejected){}//Promise函数对象的方法:resolve,返回一个成功值为value的promise对象Promise.resolve=function(value){}//Promise函数对象的方法:reject,返回一个失败值为reason的promise对象Promise.reject=function(reason){}//Promise函数对象的方法:all(接收参数为promise的数组),返回promise对象构成数组(都成功时)Promise.all=function(promises){}//Promise函数对象的方法:race(接收参数为promise的数组),返回promise对象(第一个完成的)Promise.race=function(promises){}//向外暴露这个Promise函数,绑定为window的属性window.Promise=Promise
})(window)

二,构造函数Promise的实现

第一步:因为excutor是立即同步执行的,所以在promise函数内部需要调用这个excutor函数,并且参数是resolve和reject这两个回调函数。
第二步:因为参数是这两个回调函数,所以这两个回调函数就需要事先定义好。
第三步:根据平时对promise的使用,可以知道,promise必然有个状态属性(peding,resolve,reject),还有一个用于存储结果的属性,还有一个存储回调函数的数组:

//es5里面自定义模块,用的是IIFE(函数自调用)
(function(window){//定义promise构造函数//参数是excutor函数:同步执行function Promise(excutor){//因为后面resolve和reject是程序员使用者直接在外面调用,this会变成window,故这里保存一下const that=thisthat.status='pending'  //给promise对象指定状态属性,初始值为pendingthat.data=undefined  //给promise对象指定一个用于存储结果数据的属性that.callbacks=[]   //放回调函数的,每个元素的结构:{ onResolved(){},onRejected(){} }function resolve(value){//如果状态不是pending,直接结束if(that.status!=='pending'){return}//将状态改为resolvedthat.status='resolved'//保存value数据that.data=value//如果有待执行的callback函数,立即异步执行回调函数onResolvedif(that.callbacks.length>0){setTimeout(()=>{//让他异步执行,所有成功的回调that.callbacks.forEach(callbacksObj=>{callbacksObj.onResolved(value)})})}}function reject(reason){//如果状态不是pending,直接结束if(that.status!=='pending'){return}//将状态改为rejectedthat.status='rejected'//保存reason数据that.data=reason//如果有待执行的callback函数,立即异步执行回调函数onRejectedif(that.callbacks.length>0){setTimeout(()=>{//让他异步执行,所有成功的回调that.callbacks.forEach(callbacksObj=>{callbacksObj.onRejected(reason)})})}}//需要立即同步执行excutor函数,但他需要两个回调函数作为参数,故在这之前需要先定义好这两个回调函数try{excutor(resolve,reject)}catch(error){  //如果执行器抛出异常,promise对象变为rejected状态reject(error)}}// Promise原型对象的then方法,两个参数是回调函数(成功和失败),返回一个新的promise对象Promise.prototype.then=function (onResolved,onRejected){//假设当前状态还是pending状态,将回调函数保存起来this.callbacks.push({onResolved,onRejected})}// Promise原型对象的catch方法,一个参数是回调函数(失败),返回一个新的promise对象Promise.prototype.catch=function (onRejected){}//Promise函数对象的方法:resolve,返回一个成功值为value的promise对象Promise.resolve=function(value){}//Promise函数对象的方法:reject,返回一个失败值为reason的promise对象Promise.reject=function(reason){}//Promise函数对象的方法:all(接收参数为promise的数组),返回promise对象构成数组(都成功时)Promise.all=function(promises){}//Promise函数对象的方法:race(接收参数为promise的数组),返回promise对象(第一个完成的)Promise.race=function(promises){}//向外暴露这个Promise函数,绑定为window的属性window.Promise=Promise
})(window)

也就是说:这部分是excutor实参,

而在promise构造函数内部,第一个执行的就是这个实参函数:

而这里面调用了resolve(1),这个1类比于异步操作的结果
于是就去执行resolve函数,也就是说resolve是定义者定义在promise中,使用者在外面异步操作完成后调用。
而resolve里还要调用.then中的函数:

简单写:


这样就是先指定两个回调函数,等resolve调用时,就可以直接在callbacks里面找到并使用了。

三,then方法的实现

//es5里面自定义模块,用的是IIFE(函数自调用)
(function(window){const PENDING='pending'const RESOLVED='resolved'const REJECTED='rejected'//定义promise构造函数//参数是excutor函数:同步执行function Promise(excutor){//因为后面resolve和reject是程序员使用者直接在外面调用,this会变成window,故这里保存一下const that=thisthat.status=PENDING  //给promise对象指定状态属性,初始值为pendingthat.data=undefined  //给promise对象指定一个用于存储结果数据的属性that.callbacks=[]   //放回调函数的,每个元素的结构:{ onResolved(){},onRejected(){} }function resolve(value){//如果状态不是pending,直接结束if(that.status!==PENDING){return}//将状态改为resolvedthat.status=RESOLVED//保存value数据that.data=value//如果有待执行的callback函数,立即异步执行回调函数onResolvedif(that.callbacks.length>0){setTimeout(()=>{//让他异步执行,所有成功的回调that.callbacks.forEach(callbacksObj=>{callbacksObj.onResolved(value)})})}}function reject(reason){//如果状态不是pending,直接结束if(that.status!==PENDING){return}//将状态改为rejectedthat.status=REJECTED//保存reason数据that.data=reason//如果有待执行的callback函数,立即异步执行回调函数onRejectedif(that.callbacks.length>0){setTimeout(()=>{//让他异步执行,所有成功的回调that.callbacks.forEach(callbacksObj=>{callbacksObj.onRejected(reason)})})}}//需要立即同步执行excutor函数,但他需要两个回调函数作为参数,故在这之前需要先定义好这两个回调函数try{excutor(resolve,reject)}catch(error){  //如果执行器抛出异常,promise对象变为rejected状态reject(error)}}// Promise原型对象的then方法,两个参数是回调函数(成功和失败),返回一个新的promise对象Promise.prototype.then=function (onResolved,onRejected){//默认的成功回调函数onResolved=typeof onResolved === 'function' ? onResolved : value=>value//指定默认的失败的回调(实现错误/异常传透的关键点)onRejected=typeof onRejected === 'function' ? onRejected : reason=>{throw reason}const that=this//返回一个新的promise对象,里面的参数依旧是excutor函数return new Promise((resolve,reject)=>{//调用指定的回调函数来处理那三种返回值的情况// 1,如果抛出异常,新promise变为rejected状态,reason为抛出的异常// 2,如果返回的是非promise的任意值,新promise变为resolved,value为返回的值。// 3,如果返回的是另一个新的promise,此promise的结果就会变成新promise的结果function handle(callback){try{const result =callback(that.data)if(result instanceof Promise){  //判断返回是promise的实例对象result.then(value=>resolve(value), //当result成功时,让return的promise也成功reason=>reject(reason)  //当result失败时,让return的promise也失败)}else{   //返回是非promise的任意值,新promise变为resolved,value为返回的值。resolve(result)}}catch(error){   //这里写得是then的回调函数里面,抛出异常了,新promise变为rejected状态,reason为抛出的异常reject(error)}}if(that.status===PENDING){//假设当前状态还是pending状态,此时是先指定回调函数,后改变状态。将回调函数保存起来//因为需要改状态,所以这样写,而不是直接handle(onResolved)this.callbacks.push({onResolved(value){handle(onResolved)},onRejected(reason){handle(onRejected)}})}else if(that.status===RESOLVED){//现在已经成功了,必然已经执行了resolve函数,所以结果必然存储在this.status里面setTimeout(()=>{handle(onResolved)})}else{//现在已经失败,必然已经执行了reject函数,所以结果必然存储在this.status里面setTimeout(()=>{handle(onRejected)})}})}// Promise原型对象的catch方法,一个参数是回调函数(失败),返回一个新的promise对象Promise.prototype.catch=function (onRejected){return this.then(undefined,onRejected)}//Promise函数对象的方法:resolve,返回一个成功值为value的promise对象Promise.resolve=function(value){}//Promise函数对象的方法:reject,返回一个失败值为reason的promise对象Promise.reject=function(reason){}//Promise函数对象的方法:all(接收参数为promise的数组),返回promise对象构成数组(都成功时)Promise.all=function(promises){}//Promise函数对象的方法:race(接收参数为promise的数组),返回promise对象(第一个完成的)Promise.race=function(promises){}//向外暴露这个Promise函数,绑定为window的属性window.Promise=Promise
})(window)

四,Promise.resolve和reject的实现

//Promise函数对象的方法:resolve,返回一个成功值为value的promise对象Promise.resolve=function(value){//返回一个promise成功/失败return new Promise((resolve,reject)=>{//value是一个promise时if(value instanceof Promise){//根据value的结果作为pormise的结果value.then(value=>resolve(value), //当result成功时,让return的promise也成功reason=>reject(reason)  //当result失败时,让return的promise也失败)}else{ //value不是一个promise=>promise变为成功,数据是valueresolve(value)}})}//Promise函数对象的方法:reject,返回一个失败值为reason的promise对象Promise.reject=function(reason){//返回一个失败的promisereturn new Promise((resolve,reject)=>{reject(reason)})}

五,Promise.all方法

//Promise函数对象的方法:all(接收参数为promise的数组),返回promise对象构成数组(都成功时)Promise.all=function(promises){const values =new Array(promises.length)let acount=0return new Promise((resolve,reject)=>{//遍历获取每一个promises内部的promisepromises.forEach((p,index)=>{p.then(value=>{//p成功,将成功的value保存到values里,且要按顺序values[index]=value//如果全部成功了,就将return的promise改变为成功acount++if(acount===promises.length){resolve(values)}},reason=>{  //只要一个失败了,return的promise函数就失败reject(reason)})})})}

六,Promise.race方法

//Promise函数对象的方法:race(接收参数为promise的数组),返回promise对象(第一个完成的)Promise.race=function(promises){return new Promise((resolve,reject)=>{//遍历获取每一个promises内部的promisepromises.forEach((p,index)=>{p.then(value=>{//一旦有成功的,把return变为成功promiseresolve(value)},reason=>{  //一旦有失败的,把return变为失败promisereject(reason)})})})

七,整体的promise

//es5里面自定义模块,用的是IIFE(函数自调用)
(function(window){const PENDING='pending'const RESOLVED='resolved'const REJECTED='rejected'//定义promise构造函数//参数是excutor函数:同步执行function Promise(excutor){//因为后面resolve和reject是程序员使用者直接在外面调用,this会变成window,故这里保存一下const that=thisthat.status=PENDING  //给promise对象指定状态属性,初始值为pendingthat.data=undefined  //给promise对象指定一个用于存储结果数据的属性that.callbacks=[]   //放回调函数的,每个元素的结构:{ onResolved(){},onRejected(){} }function resolve(value){//如果状态不是pending,直接结束if(that.status!==PENDING){return}//将状态改为resolvedthat.status=RESOLVED//保存value数据that.data=value//如果有待执行的callback函数,立即异步执行回调函数onResolvedif(that.callbacks.length>0){setTimeout(()=>{//让他异步执行,所有成功的回调that.callbacks.forEach(callbacksObj=>{callbacksObj.onResolved(value)})})}}function reject(reason){//如果状态不是pending,直接结束if(that.status!==PENDING){return}//将状态改为rejectedthat.status=REJECTED//保存reason数据that.data=reason//如果有待执行的callback函数,立即异步执行回调函数onRejectedif(that.callbacks.length>0){setTimeout(()=>{//让他异步执行,所有成功的回调that.callbacks.forEach(callbacksObj=>{callbacksObj.onRejected(reason)})})}}//需要立即同步执行excutor函数,但他需要两个回调函数作为参数,故在这之前需要先定义好这两个回调函数try{excutor(resolve,reject)}catch(error){  //如果执行器抛出异常,promise对象变为rejected状态reject(error)}}// Promise原型对象的then方法,两个参数是回调函数(成功和失败),返回一个新的promise对象Promise.prototype.then=function (onResolved,onRejected){//默认的成功回调函数onResolved=typeof onResolved === 'function' ? onResolved : value=>value//指定默认的失败的回调(实现错误/异常传透的关键点)onRejected=typeof onRejected === 'function' ? onRejected : reason=>{throw reason}const that=this//返回一个新的promise对象,里面的参数依旧是excutor函数return new Promise((resolve,reject)=>{//调用指定的回调函数来处理那三种返回值的情况// 1,如果抛出异常,新promise变为rejected状态,reason为抛出的异常// 2,如果返回的是非promise的任意值,新promise变为resolved,value为返回的值。// 3,如果返回的是另一个新的promise,此promise的结果就会变成新promise的结果function handle(callback){try{const result =callback(that.data)if(result instanceof Promise){  //判断返回是promise的实例对象result.then(value=>resolve(value), //当result成功时,让return的promise也成功reason=>reject(reason)  //当result失败时,让return的promise也失败)}else{   //返回是非promise的任意值,新promise变为resolved,value为返回的值。resolve(result)}}catch(error){   //这里写得是then的回调函数里面,抛出异常了,新promise变为rejected状态,reason为抛出的异常reject(error)}}if(that.status===PENDING){//假设当前状态还是pending状态,此时是先指定回调函数,后改变状态。将回调函数保存起来//因为需要改状态,所以这样写,而不是直接handle(onResolved)this.callbacks.push({onResolved(value){handle(onResolved)},onRejected(reason){handle(onRejected)}})}else if(that.status===RESOLVED){//现在已经成功了,必然已经执行了resolve函数,所以结果必然存储在this.status里面setTimeout(()=>{handle(onResolved)})}else{//现在已经失败,必然已经执行了reject函数,所以结果必然存储在this.status里面setTimeout(()=>{handle(onRejected)})}})}// Promise原型对象的catch方法,一个参数是回调函数(失败),返回一个新的promise对象Promise.prototype.catch=function (onRejected){return this.then(undefined,onRejected)}//Promise函数对象的方法:resolve,返回一个成功值为value的promise对象Promise.resolve=function(value){//返回一个promise成功/失败return new Promise((resolve,reject)=>{//value是一个promise时if(value instanceof Promise){//根据value的结果作为pormise的结果value.then(value=>resolve(value), //当result成功时,让return的promise也成功reason=>reject(reason)  //当result失败时,让return的promise也失败)}else{ //value不是一个promise=>promise变为成功,数据是valueresolve(value)}})}//Promise函数对象的方法:reject,返回一个失败值为reason的promise对象Promise.reject=function(reason){//返回一个失败的promisereturn new Promise((resolve,reject)=>{reject(reason)})}//Promise函数对象的方法:all(接收参数为promise的数组),返回promise对象构成数组(都成功时)Promise.all=function(promises){const values =new Array(promises.length)let acount=0return new Promise((resolve,reject)=>{//遍历获取每一个promises内部的promisepromises.forEach((p,index)=>{p.then(value=>{//p成功,将成功的value保存到values里,且要按顺序values[index]=value//如果全部成功了,就将return的promise改变为成功acount++if(acount===promises.length){resolve(values)}},reason=>{  //只要一个失败了,return的promise函数就失败reject(reason)})})})}//Promise函数对象的方法:race(接收参数为promise的数组),返回promise对象(第一个完成的)Promise.race=function(promises){return new Promise((resolve,reject)=>{//遍历获取每一个promises内部的promisepromises.forEach((p,index)=>{p.then(value=>{//一旦有成功的,把return变为成功promiseresolve(value)},reason=>{  //一旦有失败的,把return变为失败promisereject(reason)})})})}//向外暴露这个Promise函数,绑定为window的属性window.Promise=Promise
})(window)

自定义Promise相关推荐

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

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

  2. Promise 化回调式函数

    [RTC实时互联网大会 限时免费 马上报名]www.bagevent.com Node.js 8 提供了新的工具函数:util.promisify,用于把形如 (err, value) => . ...

  3. 【es6】谈谈Promise

    学习vue写项目已经很久了,在项目中有许多地方会使用到Promise,无论前后端的接口通信,还是各种第三方的组件库或是插件,或多或少都会发现Promise的影子,所以今天简单梳理一下关于Promise ...

  4. 如何将文件地址转为url_Node.js 源码解析 util.promisify 如何将 Callback 转为 Promise

    Nodejs util 模块提供了很多工具函数.为了解决回调地狱问题,Nodejs v8.0.0 提供了 promisify 方法可以将 Callback 转为 Promise 对象. 工作中对于一些 ...

  5. 聊一聊promise的前世今生

    promise的概念已经出现很久了,浏览器.nodejs都已经全部实现promise了.现在来聊,是不是有点过时了? 确实,如果不扯淡,这篇随笔根本不会有太多内容.所以,我就尽可能的,多扯一扯,聊一聊 ...

  6. 定时器和promise_手写Promise核心原理,再也不怕面试官问我Promise原理

    整体流程的介绍 整体流程的介绍 1. 定义整体结构 2. 实现Promise构造函数 3. 实现then方法 3.实现catch方法 4. 实现Promise.resolve 5.实现Promise. ...

  7. callback函数_Nodejs 源码解析 util.promisify 如何将 Callback 转为 Promise

    Nodejs util 模块提供了很多工具函数.为了解决回调地狱问题,Nodejs v8.0.0 提供了 promisify 方法可以将 Callback 转为 Promise 对象. 工作中对于一些 ...

  8. 一篇文章理解Promise原理

    前提掌握知识: 微任务包括: MutationObserver.Promise.then()或reject().Promise为基础开发的其它技术,比如fetch API.V8的垃圾回收过程.Node ...

  9. Promise: 手写Promise

    前言 ES6里的Promise是个原理性蛮复杂但是使用起来很简单的异步解决方案.我们有必要系统.深入的学习Promise的使用规则,并能根据规则手动实现一个完整的Promise,下面我们就根据官方的规 ...

  10. 07前端基础--Promise用法

    一.实例对象和函数对象: 函数对象:将函数作为对象使用时,简称为函数对象,操作它的属性或方法时,用. 实例对象:new 函数产生的对象,简称对象 JS只所有函数都是Function类的实例对象,cal ...

最新文章

  1. 《OpenCV3编程入门》学习笔记8 图像轮廓与图像分割修复(三)使用多边形将轮廓包围
  2. printstream java_Java PrintStream
  3. C基础 redis缓存访问
  4. git基本概念与核心命令_Git:了解核心版本控制概念的初学者指南
  5. 韩顺平php视频笔记36 php基本语法
  6. 吴恩达深度学习2.2笔记_Improving Deep Neural Networks_优化算法
  7. opengl 旋转矩阵和纹理坐标相乘_OpenGL-Rotating Points
  8. 小程序商城和h5商城那个比较好?
  9. 最全面计算机英语单词列表(一)
  10. 三对角矩阵解算——TDMA解法(C++)
  11. mysql临时表插入数据
  12. 北京3月去哪玩 赏花踏青登山六大推荐
  13. Moveit更换默认规划器KDL为TraceIk
  14. 编码至高法则-高内聚低耦合
  15. CTF基础知识与web信息泄露下的目录遍历、PHPINFO、备份文件下载
  16. 泰服游戏服务器如何显示中文,【战争机器不能显示中文怎么解决】如何解决_战争机器中文设置教程_游戏城...
  17. python读取word内容复制粘贴_如何复制word文档的内容?
  18. 走到哪里都有我们的精彩
  19. 直播回顾丨一堂课快速上手EdgeX
  20. c语言 的意思啊,c语言中!1是什么意思啊

热门文章

  1. Raki的读paper小记:Rational LAMOL: A Rationale-Based Lifelong Learning Framework
  2. linux系统怎么启动服务器,Linux操作系统的启动步骤详细说明
  3. html是描述型语言,JavaScript_JavaScript基础教程——入门必看篇,JavaScript他是一种描述性语言, - phpStudy...
  4. 洛谷P1141 01迷宫【bfs】
  5. JVM内存模型及垃圾回收机制
  6. JS下滑菜单,向下滑出二级导航
  7. java对象创建、对象内存布局、对象的访问定位、句柄池、直接指针
  8. 配置docker加速器
  9. Spring Boot不指定包路径就可以扫描启动类所在包及其子包下的类是怎么做到的?
  10. 【Hoxton.SR1版本】Spring Cloud Bus消息总线