手写基于Promise A+规范的Promise

const PENDING =  ‘pending‘;//初始态const FULFILLED =  ‘fulfilled‘;//初始态const REJECTED =  ‘rejected‘;//初始态function Promise(executor){  let self = this;//先缓存当前promise实例  self.status = PENDING;//设置状态  //定义存放成功的回调的数组  self.onResolvedCallbacks = [];  //定义存放失败回调的数组  self.onRejectedCallbacks = [];  //当调用此方法的时候,如果promise状态为pending,的话可以转成成功态,如果已经是成功态或者失败态了,则什么都不做  //2.1  function resolve(value){ //2.1.1    if(value!=null &&value.then&&typeof value.then == ‘function‘){      return value.then(resolve,reject);    }    //如果是初始态,则转成成功态    setTimeout(function(){      if(self.status == PENDING){        self.status = FULFILLED;        self.value = value;//成功后会得到一个值,这个值不能改        //调用所有成功的回调        self.onResolvedCallbacks.forEach(cb=>cb(self.value));      }    })

}  function reject(reason){ //2.1.2    setTimeout(function(){      //如果是初始态,则转成失败态      if(self.status == PENDING){        self.status = REJECTED;        self.value = reason;//失败的原因给了value        self.onRejectedCallbacks.forEach(cb=>cb(self.value));      }    });

}  try{    //因为此函数执行可能会异常,所以需要捕获,如果出错了,需要用错误 对象reject    executor(resolve,reject);  }catch(e){    //如果这函数执行失败了,则用失败的原因reject这个promise    reject(e);  };}function resolvePromise(promise2,x,resolve,reject){  if(promise2 === x){    return reject(new TypeError(‘循环引用‘));  }  let called = false;//promise2是否已经resolve 或reject了  if(x instanceof Promise){    if(x.status == PENDING){      x.then(function(y){        resolvePromise(promise2,y,resolve,reject);      },reject);    }else{      x.then(resolve,reject);    }  //x是一个thenable对象或函数,只要有then方法的对象,  }else if(x!= null &&((typeof x==‘object‘)||(typeof x == ‘function‘))){    //当我们的promise和别的promise进行交互,编写这段代码的时候尽量的考虑兼容性,允许别人瞎写   try{     let then = x.then;     if(typeof then == ‘function‘){       //有些promise会同时执行成功和失败的回调       then.call(x,function(y){         //如果promise2已经成功或失败了,则不会再处理了          if(called)return;          called = true;          resolvePromise(promise2,y,resolve,reject)       },function(err){         if(called)return;         called = true;         reject(err);       });     }else{       //到此的话x不是一个thenable对象,那直接把它当成值resolve promise2就可以了       resolve(x);     }   }catch(e){     if(called)return;     called = true;     reject(e);   }

}else{    //如果X是一个普通 的值,则用x的值去resolve promise2    resolve(x);  }}//onFulfilled 是用来接收promise成功的值或者失败的原因Promise.prototype.then = function(onFulfilled,onRejected){  //如果成功和失败的回调没有传,则表示这个then没有任何逻辑,只会把值往后抛  //2.2.1  onFulfilled = typeof onFulfilled == ‘function‘?onFulfilled:function(value){return  value};  onRejected = typeof onRejected == ‘function‘?onRejected:reason=>{throw reason};  //如果当前promise状态已经是成功态了,onFulfilled直接取值  let self = this;  let promise2;  if(self.status == FULFILLED){    return promise2 = new Promise(function(resolve,reject){      setTimeout(function(){        try{          let x =onFulfilled(self.value);          //如果获取到了返回值x,会走解析promise的过程          resolvePromise(promise2,x,resolve,reject);        }catch(e){          //如果执行成功的回调过程中出错了,用错误原因把promise2 reject          reject(e);        }      })

});  }  if(self.status == REJECTED){    return promise2 = new Promise(function(resolve,reject){      setTimeout(function(){        try{          let x =onRejected(self.value);          resolvePromise(promise2,x,resolve,reject);        }catch(e){          reject(e);        }      })    });  }  if(self.status == PENDING){   return promise2 = new Promise(function(resolve,reject){     self.onResolvedCallbacks.push(function(){         try{           let x =onFulfilled(self.value);           //如果获取到了返回值x,会走解析promise的过程           resolvePromise(promise2,x,resolve,reject);         }catch(e){           reject(e);         }

});     self.onRejectedCallbacks.push(function(){         try{           let x =onRejected(self.value);           resolvePromise(promise2,x,resolve,reject);         }catch(e){           reject(e);         }     });   });  }

}//catch原理就是只传失败的回调Promise.prototype.catch = function(onRejected){    this.then(null,onRejected);}Promise.deferred = Promise.defer = function(){  let defer = {};  defer.promise = new Promise(function(resolve,reject){    defer.resolve = resolve;    defer.reject = reject;  });  return defer;}function gen(times,cb){  let result = [],count=0;  return function(i,data){    result[i] = data;    if(++count==times){      cb(result);    }  }}Promise.all = function(promises){ return new Promise(function(resolve,reject){   let done = gen(promises.length,resolve);   for(let i=0;i<promises.length;i++){     promises[i].then(function(data){       done(i,data);     },reject);   } });}Promise.race = function(promises){  return new Promise(function(resolve,reject){    for(let i=0;i<promises.length;i++){      promises[i].then(resolve,reject);    }  });}//返回一个立刻成功的promise//别人提供 给你一个方法,需要你传入一个promise,但你只有一个普通的值,你就可以通过这个方法把这个普通的值(string number object)转成一个promise对象Promise.resolve = function(value){  return new Promise(function(resolve){    resolve(value);  });}//返回一个立刻失败的promisePromise.reject = function(reason){  return new Promise(function(resolve,reject){    reject(reason);  });}module.exports = Promise;

原文地址:https://www.cnblogs.com/qinmengjiao123-123/p/8280973.html

时间: 2024-10-11 11:22:32

手写基于Promise A+规范的Promise的相关文章

深入理解Promise并写一个符合Promise a+规范的Promise代码

关于Promise函数可以参考我写的这篇文章https://www.cnblogs.com/qiaohong/p/7705262.html,我们现在就深入理解一下这个函数. 首先说下Promise方法,Promise方法中还是有些是比较好用的,比如说Promise.all()方法(Promise.all()方法的参数是一个数组,会按照数组的结果放到成功的回调里,如果有一个错误那么就不会成功).Promise.race()方法(这个方法的参数也是一个数组,Promise.race()会同时发起并发

一步一步实现一个Promise A+规范的 Promise

2015年6月,ES2015(即ES6)正式发布后受到了非常多的关注.其中很重要的一点是 Promise 被列为了正式规范. 在此之前很多库都对异步编程/回调地狱实现了类 Promise 的应对方案,比如 bluebird.Angular 的 Q 和大名鼎鼎的 jQuery 的 deffered 等. 为了便于理解,本文将分为三个部分,每个部分实现 Promise 的一部分特性,最终一步一步的实现一个完整的.遵循 promise A+ 规范的 Promise. Promise A+规范规定,Pr

带你手写基于 Spring 的可插拔式 RPC 框架(二)整体结构

前言 上一篇文章中我们已经知道了什么是 RPC 框架和为什么要做一个 RPC 框架了,这一章我们来从宏观上分析,怎么来实现一个 RPC 框架,这个框架都有那些模块以及这些模块的作用. 总体设计 在我们的整个框架里比较重要的几个模块: rpc-procotol: 既然是可插拔是框架,我们需要支持选择底层协议,这部分是通信协议相关的模块. rpc-spring: 我们的框架是基于 spring 开发的,这个模块是将我们的一些功能和 spring 整合起来,比如自动注入代理 bean,启动服务端 se

带你手写基于 Spring 的可插拔式 RPC 框架(三)通信协议模块

在写代码之前我们先要想清楚几个问题. 我们的框架到底要实现什么功能? 我们要实现一个远程调用的 RPC 协议. 最终实现效果是什么样的? 我们能像调用本地服务一样调用远程的服务. 怎样实现上面的效果? 前面几章已经给大家说了,使用动态代理,在客户端生成接口代理类使用,在代理类的 invoke 方法里面将方法参数等信息组装成 request 发给服务端,服务端需要起一个服务器一直等待接收这种消息,接收之后使用反射调 用对应接口的实现类. 首先我们需要实现底层的通信的服务端和客户端,可以有一下几种实

带你手写基于 Spring 的可插拔式 RPC 框架(四)代理类的注入与服务启动

上一章节我们已经实现了从客户端往服务端发送数据并且通过反射方法调用服务端的实现类最后返回给客户端的底层协议. 这一章节我们来实现客户端代理类的注入. 承接上一章,我们实现了多个底层协议,procotol 有 netty,http,和 socket 三个实现类,每个实现类都有启动服务端和客户端发送数据两个方法. 问题 如何实现底层协议的选择那? 可以通过配置文件来选择协议. 单独的配置文件还是和 Spring 的配置文件结合起来那? 我们选择与 Spring 结合的配置文件,自定义一些属性的标签,

带你手写基于 Spring 的可插拔式 RPC 框架(一)介绍

概述 首先这篇文章是要带大家来实现一个框架,听到框架大家可能会觉得非常高大上,其实这和我们平时写业务员代码没什么区别,但是框架是要给别人使用的,所以我们要换位思考,怎么才能让别人用着舒服,怎么样才能让我们的框架性能优异.通过自己写一个框架,我们能学到的有很多,能让我们脱离 CURD,在更高的层面上去思考. 目的 写这个框架最主要的目的是要让大家了解整个框架的设计思想和用到的技术,并不是让大家关注代码,当然我实现的代码一定不是完美的,还有很多需要改进的地方,希望大家不吝赐教,一起进步. 提前准备

带你手写基于 Spring 的可插拔式 RPC 框架(五)注册中心

注册中心代码使用 zookeeper 实现,通过图片来看看我们注册中心的架构. 首先说明, zookeeper 的实现思路和代码是参考架构探险这本书上的,另外在 github 和我前面配置文件中的 zookeeper 服务器是用的1个月免费适用的阿里云,大家也可以用它当测试用. 不多说,一次性给出注册中心全部代码. 客户端对应的注册中心接口 public interface RegisterCenter4Consumer { /** * 消费端初始化服务提供者信息本地缓存 */ public v

手写 Promise

在上一章节中我们了解了 Promise 的一些易错点,在这一章节中,我们会通过手写一个符合 Promise/A+ 规范的 Promise 来深入理解它,并且手写 Promise 也是一道大厂常考题,在进入正题之前,推荐各位阅读一下 Promise/A+ 规范,这样才能更好地理解这个章节的代码. 实现一个简易版 Promise 在完成符合 Promise/A+ 规范的代码之前,我们可以先来实现一个简易版 Promise,因为在面试中,如果你能实现出一个简易版的 Promise 基本可以过关了. 那

手写promise进阶版本

promise/A+规范: 术语: 1.promise是一个对象或者函数,该对象或者函数有一个then方法 2.thenable是一个函数或者对象,用来定义then方法 3.value是promise成功时的状态值 4.reason是promise失败时的状态值 要求:一.二 一. 1.三种状态 :pending | fulfilled(resolved) | rejected 2.rejected当处于pending状态的时候,可以转移到fulfilled(resolved)或者rejecte