预备知识

  • 回调函数
  • 高级函数
  • 发布-订阅模式
  • promise A+ 规范

promise是什么,能干什么

Promise是异步编程的一种解决方案,它可以解决异步回调地狱的问题,防止层层嵌套对程序代码带来的难维护性。既然带来了方便,我们就有必要学习它的原理以及底层实现,所以笔者就按照PromiseA+规范写了一个简单的Promise,并实现了Promise.all(),Promise.race()等API

  • 解决回调地狱
  • 解决多个回调函数同步结果

promise的几个方法

  • promise.all()
  • promise.race()
  • promise.resolve()
  • promise.reject()

promise的三种状态

  • 等待态 pending
  • 成功态 resolved
  • 失败态 rejected

promise的特点

  • 1.executor 默认时new的时候就自动执行
  • 2.每个promise的实例 都有then方法
  • 3.then方法中有两个参数 分别是成功的回调和失败的回调
  • 4.then方法是异步的(微任务) // 微任务先于宏任务执行
  • 5.同一个promise的实例可以then多次,成功时回调用所有的成功方法,失败时会调用所有的失败方法
  • 6.new Promise中可以支持异步行为
  • 7.如果发现错误就会走入失败态

下一次的输入需要上一次的输出 (有依赖关系)

  • 1.如果一个promise执行完后 返回的还是一个promise,会把这个promise 的执行结果,传递给下一次then中
  • 2.如果then中返回的不是promise 是一个普通值,会将这个普通值作为下次then的成功的结果
  • 3.如果当前then中失败了 会走下一个then的失败
  • 4.如果返回的是undefined 不管当前是成功还是失败 都会走下一次的成功
  • 5.catch是错误没有处理的情况下才会走
  • 6.then中可以不写东西,相当于白写 (值的穿透)

promise A+ 规范

  • 原文
  • 翻译
  • 校验插件 npm install promises-aplus-tests -g 用于检查自己写的promise是否符合promise规范

简单实现 待完善

    function Promise(executor){let self = this;self.value = undefined; // 成功时的参数self.reason = undefined; // 失败时的参数self.status = 'pending'; // 状态 self.onResolvedCallbacks = [];// 存放then中成功的回调 self.onRejectedCallbacks = []; // 存放then中失败的回调 function resolve(value){ // if(self.status === 'pending'){self.value = value;self.status = 'resolved';self.onResolvedCallbacks.forEach(fn=>fn());}}function reject(reason){if(self.status === 'pending'){self.reason = reason;self.status = 'rejected';self.onRejectedCallbacks.forEach(fn=>fn());}}// 如果函数执行时发生异常 就走到失败中try{executor(resolve,reject);}catch(e){reject(e);}
}
Promise.prototype.then = function(onFulfilled,onRejected){let self = this;if(self.status === 'resolved'){onFulfilled(self.value);}if(self.status === 'rejected'){onRejected(self.reason);}if(self.status === 'pending'){// 保存回调函数self.onResolvedCallbacks.push(()=>{onFulfilled(self.value);});self.onRejectedCallbacks.push(()=>{onRejected(self.reason)});}
}
module.exports = Promise;
复制代码

基本实现

function Promise(executor) {let self = this;self.value = undefined; // 成功的值self.reason = undefined; // 失败的原因self.status = 'pending'; // 值是pending状态self.onResolvedCallbacks = []; // 可能new Promise的时候会有异步操作,保存成功和失败的回调 self.onRejectedCallbacks = [];function resolve(value) { // 把状态改成成功态if (self.status === 'pending') { // 只有等待态 可以改变状态self.value = value;self.status = 'resolved';self.onResolvedCallbacks.forEach(fn => fn());}}function reject(reason) { // 把状态改成失败态if (self.status === 'pending') {self.reason = reason;self.status = 'rejected';self.onRejectedCallbacks.forEach(fn => fn());}}try {// 默认new Promise时 应该执行对应的执行器(同步执行)executor(resolve, reject);} catch (e) { // 如果执行exectuor时 发生错误 就会让当前的promise变成失败态reject(e);}
}
/*** * @param {*} promise2  then的返回值 (返回的新的promise)* @param {*} x  then中成功或者失败函数的返回值* @param {*} resolve promise2的resolve* @param {*} reject  promise2的reject*/
// 所有的promise都遵循这个规范 (所有的promise可以通用)function resolvePromise(promise2,x,resolve,reject){// promise2和函数执行后返回的结果是同一个对象if(promise2 === x){ return reject(new TypeError('Chaining cycle'));}let called;// x可能是一个promise 或者是一个普通值if(x!==null && (typeof x=== 'object' || typeof x === 'function')){try{let then = x.then; // 取对象上的属性 怎么能报异常呢?(这个promise不一定是自己写的 可能是别人写的 有的人会乱写)// x可能还是一个promise 那么就让这个promise执行即可// {then:{}}// 这里的逻辑不单单是自己的 还有别人的 别人的promise 可能既会调用成功 也会调用失败if(typeof then === 'function'){then.call(x,y=>{ // 返回promise后的成功结果// 递归直到解析成普通值为止if(called) return; // 防止多次调用called = true;// 递归 可能成功后的结果是一个promise 那就要循环的去解析resolvePromise(promise2,y,resolve,reject);},err=>{ // promise的失败结果if(called) return;called = true;reject(err);});}else{resolve(x);}}catch(e){if(called) return;called = true;reject(e);}}else{ // 如果x是一个常量resolve(x);}
}
// then调用的时候 都是异步调用 (原生的then的成功或者失败 是一个微任务)
Promise.prototype.then = function (onFulfilled, onRejected) {// 成功和失败的回调 是可选参数// onFulfilled成功的回调 onRejected失败的回调let self = this;let promise2;// 需要没次调用then时都返回一个新的promisepromise2 = new Promise((resolve, reject) => {if (self.status === 'resolved') {setTimeout(()=>{try {// 当执行成功回调的时候 可能会出现异常,那就用这个异常作为promise2的错误的结果let x = onFulfilled(self.value);//执行完当前成功回调后返回结果可能是promiseresolvePromise(promise2,x,resolve,reject);} catch (e) {reject(e);}},0)}if (self.status === 'rejected') {setTimeout(()=>{try {let x = onRejected(self.reason);resolvePromise(promise2,x,resolve,reject);} catch (e) {reject(e);}},0)}if (self.status === 'pending') {self.onResolvedCallbacks.push(() => {setTimeout(()=>{try {let x = onFulfilled(self.value);resolvePromise(promise2,x,resolve,reject);} catch (e) {reject(e);}},0)});self.onRejectedCallbacks.push(() => {setTimeout(()=>{try {let x = onRejected(self.reason);resolvePromise(promise2,x,resolve,reject);} catch (e) {reject(e);}},0)});}});return promise2
}
// 为什么加setTimeout (规范要求的)Promise.defer = Promise.deferred = function(){let dfd = {};dfd.promise = new Promise((resolve,reject)=>{dfd.resolve = resolve;dfd.reject = reject;})return dfd;
}
module.exports = Promise;
复制代码

最终版本

function Promise(executor) {let self = this;self.value = undefined; self.reason = undefined; self.status = 'pending';self.onResolvedCallbacks = [];self.onRejectedCallbacks = [];function resolve(value) { if (self.status === 'pending') {self.value = value;self.status = 'resolved';self.onResolvedCallbacks.forEach(fn => fn());}}function reject(reason) { if (self.status === 'pending') {self.reason = reason;self.status = 'rejected';self.onRejectedCallbacks.forEach(fn => fn());}}try {executor(resolve, reject);} catch (e) { reject(e);}
}
function resolvePromise(promise2,x,resolve,reject){if(promise2 === x){return reject(new TypeError('Chaining cycle'));}let called;if(x!==null && (typeof x=== 'object' || typeof x === 'function')){try{let then = x.then; if(typeof then === 'function'){then.call(x,y=>{ if(called) return; called = true;resolvePromise(promise2,y,resolve,reject);},err=>{ if(called) return;called = true;reject(err);});}else{resolve(x);}}catch(e){if(called) return;called = true;reject(e);}}else{ // 如果x是一个常量resolve(x);}
}
Promise.prototype.then = function (onFulfilled, onRejected) {onFulfilled = typeof onFulfilled === 'function'?onFulfilled:val=>val;onRejected = typeof onRejected === 'function'?onRejected: err=>{throw err}let self = this;let promise2;promise2 = new Promise((resolve, reject) => {if (self.status === 'resolved') {setTimeout(()=>{try {let x = onFulfilled(self.value);resolvePromise(promise2,x,resolve,reject);} catch (e) {reject(e);}},0)}if (self.status === 'rejected') {setTimeout(()=>{try {let x = onRejected(self.reason);resolvePromise(promise2,x,resolve,reject);} catch (e) {reject(e);}},0)}if (self.status === 'pending') {self.onResolvedCallbacks.push(() => {setTimeout(()=>{try {let x = onFulfilled(self.value);resolvePromise(promise2,x,resolve,reject);} catch (e) {reject(e);}},0)});self.onRejectedCallbacks.push(() => {setTimeout(()=>{try {let x = onRejected(self.reason);resolvePromise(promise2,x,resolve,reject);} catch (e) {reject(e);}},0)});}});return promise2
}
// 语法糖 (甜) 目的是解决promise嵌套问题的 Q.derfer()
Promise.defer = Promise.deferred = function(){let dfd = {};dfd.promise = new Promise((resolve,reject)=>{dfd.resolve = resolve;dfd.reject = reject;})return dfd;
}
// 类上的方法
Promise.reject = function(reason){return new Promise((resolve,reject)=>{reject(reason);})
}
Promise.resolve = function(value){return new Promise((resolve,reject)=>{resolve(value);})
}
Promise.prototype.catch = function(onRejected){// 默认不写成功return this.then(null,onRejected);
};
// all方法
Promise.all = function(promises){return new Promise((resolve,reject)=>{let arr = [];let i = 0;function processData(index,data){arr[index] = data;if(++i == promises.length){resolve(arr);}}for(let i = 0;i<promises.length;i++){promises[i].then(data=>{ // data是成功的结果processData(i,data);},reject);}})
}
// 以请求最快的为准
Promise.race = function(promises){return new Promise((resolve,reject)=>{for(let i = 0;i<promises.length;i++){promises[i].then(resolve,reject);}})
}
module.exports = Promise;
复制代码

promise是什么?简单分析promise原理相关推荐

  1. 线程的3种实现方式并深入源码简单分析实现原理

    前言 本文介绍下线程的3种实现方式并深入源码简单的阐述下原理 三种实现方式 Thread Runnable Callable&Future 深入源码简单刨析 Thread Thread类实现了 ...

  2. 定时器和promise_分析 Promise 内部实现

    在介绍Promise之前,首先我们举一个栗子,看下面代码 function success (message) {console.log(message)}function fail (message ...

  3. 用es5实现es6的promise,彻底搞懂promise的原理

    1.promise的含义 Promise 是异步编程的一种解决方案,比传统的解决方案--回调函数和事件--更合理和更强大.它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Pr ...

  4. Nginx介绍及原理简单分析

    快速入门 ------------------------ 关于Nginx,我们可以到其官网 http://nginx.org/  以及WIKI http://wiki.nginx.org 进行下载和 ...

  5. 岭回归原理简单分析与理解

    岭回归原理简单分析与理解 首先说明一下,岭回归用于回归.学习岭回归,给我的感受是,它的数学公式推导比较简单,然而理解其含义相对难一些,所以本文着重引导你去理解它,而不仅仅是会推导公式.至于背景介绍,网 ...

  6. 手写简单版 Promise

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

  7. node js Bluebird 简单介绍 promise 解决回调地狱

    Promise是异步代码实现控制流的一种方式.这一方式可以让你的代码干净.可读并且健壮. 异步回调如下: fs.readFile('directory/file-to-read', function( ...

  8. 简单聊聊Promise

    Promise 它是一个ES6提出一个新语法,用来优化异步代码的写法. 在ES6中,它是新增的构造器(Array, Object, Promise),用来优化实现异步操作.在没有它之前,javascr ...

  9. 分析Promise,手写Promise,学习Promise,感受Promise

    整体思路分析: * 1.Promise一共有三种状态,成功fulfilled 失败rejected 等待pending  * pending => fulfilled 等待变成成功  * pen ...

最新文章

  1. MBTiles离线包生成和使用
  2. linux zynq ps dma,Zynq PS侧DMA驱动
  3. 如何获取所有Git分支
  4. 高效学习Oracle的方法论
  5. H3 BPM微信接入配置
  6. php中jquery ajax请求参数,浅谈Jquery中Ajax异步请求中的async参数的作用
  7. obj是什么意思_为什么要学正则表达式 - 3
  8. day28 socketserver
  9. Linux网络那点事
  10. “针对即席工作负荷进行优化”如何影响你的计划缓存
  11. Jsp+Ssh+Mysql实现的简单的企业物资信息管理系统
  12. 我已经弃用头条了,难道还要抛弃微信?
  13. monkey入门研究
  14. C要点5:float、double、long double(大小,范围,输入输出符,科学计数法)
  15. Jupyter Notebook设置密码且遇到提示:ImportError: DLL load failed while importing _ssl
  16. 吉他所有和弦的指型都靠硬记吗?
  17. 阿里王坚:数据重塑城市未来
  18. [转]应该怎么读Linux?
  19. php 购物车存在那个地方,php添加购物车
  20. 会考access数据库操作题_信息技术学业水平考试操作题必备!!!

热门文章

  1. Android 11 限制反射,如何破解?
  2. Windows常用命令行命令
  3. android cmd
  4. 【Angular】服务(Service)
  5. html5 head 标签
  6. 工厂方法模式与抽象工厂模式
  7. (六)docker-compose使用教程
  8. kotlin学习笔记——委托属性
  9. day 96 关于分页的使用
  10. C++入门经典-例4.1-声明、定义和使用函数