想要源码的可以看这里,里面也有一些其他的知识

想要手写一个promise,首先就要了解promise,想必大家都被过一些promise的面试题,知道一些promise的用法,主要考的就是一种异步编程的思想。

了解promise

我们先来看看直接输出一个promise对象会是什么,通过代码:

var p = new Promise((resolve,reject)=>{});
console.log(p);

可以看到输出结果Promise大致由它的状态PromiseState,它的值PromiseResult和它原型上面的方法组成。

promise对象有一个函数当作参数,函数里又分别有两个参数,分别是resolve和reject,当调用resolve()时就会运行prototype上的then()方法,当调用reject()时就会运行prototype上的catch()方法,这里的then,catch都是微任务,所谓微任务就是之宏任务运行完之后所运行的任务。就好比去银行办业务,你的要办的业务相当于宏任务,等你办完后银行工作人员会推荐与你业务相关的拓展业务,这个拓展业务就相当于微任务。

promise的状态有三种:等待(pending)、已完成(fulfilled)、已拒绝(rejected),并且状态只能由等待到完成或者等待到拒接。

开始写

了解promise之后我们就能把基本的架构写出来了。

function MyPromise(fn) {// promise 的状态this.PromiseState = "pendding";// promise 的值this.PromiseResult = undefined;var resolve = (value) => {};var reject = (errValue) => {};if (fn) {fn(resolve, reject);}}

这里定义初始状态pedding,和初始值undefined,resolve,reject两个方法。

完成then

首先先完成then的成功运作,如何能让如下代码成功输出:

var p = new MyPromise((resolve, reject) => {resolve("resolve");});p.then((res) => {console.log(res);console.log("then执行");});

这里就需要完善resolve和原型对象上写then方法:

// 定义一个函数对象,用来注册then中的callback
this.thenCallback = undefined;
var resolve = (value) => {// 更改promise的状态和值if (this.PromiseState == "pendding") {this.PromiseState = "fulfilled";this.PromiseResult = value;if (value instanceof MyPromise) {value.then((res) => {if (this.thenCallback) {this.thenCallback(res);}});} else {setTimeout(() => {if (this.thenCallback) {this.thenCallback(value);}});}}};
MyPromise.prototype.then = function (callback) {return new MyPromise((resolve, reject) => {this.thenCallback = (value) => {// 在使用链式调用的时候,可能第一个调用的不是catch// 使用我们在做检测时会借助then来将catch的信息向下传递// 所以我们检测到触发thenCallback的对象是rejected时// 我们就继续调用下一个rejectif (this.promiseState == "rejected") {reject(value);} else {var res = callback(value);// 这里防止中间返回是一个promise对象它会继续找then,直接让他调用rejectif (res instanceof MyPromise && res.promiseState == "rejected") {res.catch((errValue) => {reject(errValue);});} else {// 这里定义给变量res在调用resolve是为解决.then()的链式调用resolve(res);}}};});};

定义一个函数对象,用来注册then中的callback,首先判断promise的状态,如果是pendding则转换成fulfilled,并将参数值赋值给promiseResult;

if (value instanceof MyPromise)是为了判断value是否是一个Promise对象,如果是就使用自己定义的then,因为then时异步执行的,所以使用setTimeout

当then链式调用时,如then().then(),第一个then中如果有返回值,那么这个返回值将会作为第二个then中的参数,所以需要每个then返回一个新的promise对象return new MyPromise()。

这里再封装一个MyPromise.resolve的快捷调用:

MyPromise.resolve = (value) => {return new MyPromise((resolve, reject) => {resolve(value);});};

完成catch

catch与then大致相同,只需要稍作修改。这里完善reject方法和原型上的catch:


this.catchCallback = undefined;
var reject = (errValue) => {if (this.promiseState == "pendding") {this.promiseState = "rejected";this.promiseResult = errValue;// 判断写没写catch()setTimeout(() => {if (this.catchCallback) {this.catchCallback(errValue);} else if (this.thenCallback) {this.thenCallback(errValue);} else {throw "catch is not defined!!!!";}});}};

首先判断promise的状态,如果是pendding则转换成frejected,并将参数值赋值给promiseResult;

这里有可能再调用catch前还调用了then方法,所以使用else if判断是不是,时就运行this.thenCallback(errValue);,因为之前在then会判断promise状态是不是rejected,如果是就重新调用reject()方法。

MyPromise.prototype.catch = function (callback) {return new MyPromise((resolve, reject) => {this.catchCallback = (errValue) => {var res = callback(errValue);reject(errValue);};});};

这里也继续封装一个MyPromise.reject的快捷调用:

MyPromise.reject = (errValue) => {return new MyPromise((resolve, reject) => {reject(errValue);});};

promise中的api,all和race

all和race传入的参数都是一个数组,all将会等最长时间结束后按数组的顺序,而race则会执行最早的那一个。

MyPromise.all = (promiseArr) => {let resArr = [];return new MyPromise((resolve, reject) => {promiseArr.forEach((item, index) => {item.then((res) => {resArr[index] = res;var allResolve = promiseArr.every((_item) => {return _item.promiseState == "fulfilled";});// 判断传过来的数组中所有promise对象状态都已完成if (allResolve) {resolve(resArr);}}).catch((err) => {reject(err);});});});};
MyPromise.race = (promiseArr) => {let resArr = [];return new MyPromise((resolve, reject) => {promiseArr.forEach((item, index) => {item.then((res) => {resolve(res);}).catch((err) => {reject(err);});});});};

手写promise的化没有长时间的叙述的话不好将清楚,建议找到将promise源码的视频一步一步分析

教你如何手写一个Promise相关推荐

  1. Promise学习-手写一个promise

    学习了Promise的A+规范,以及手写一个Promise后,我对Promise学到的结果. 平常也有用到过promise来处理异步,先回顾下promise的用法 new Promise((resol ...

  2. 手写一个promise用法_手写一个 Promise

    1 js 的基本数据类型? 2 JavaScript 有几种类型的值? 3 什么是堆?什么是栈?它们之间有什么区别和联系? 4 内部属性 [Class] 是什么? 5 介绍 js 有哪些内置对象? 6 ...

  3. 手写一个promise用法_手写一个自己的 JavaScript Promise 类库

    终于有时间写这篇文章了, ES2015 推出了JS 的 Promise ,而在没有原生支持的时候,我们也可以使用诸如 Promises/A+ 的库的帮助,在我们的代码里实现Promise 的支持: 如 ...

  4. JavaScript 怎么自己手写一个Promise

    认真看完这篇文章, 您可以自己封装一个简易但功能相对齐全的Promise, 还可以加深对Promise的理解 建议 : 看这篇文章之前希望您 了解ES6的语法 [ 阮一峰老师的ES6入门 ] 了解Pr ...

  5. es6 --- 手写一个promise

    一个promise实例: var getJSON = function(url) {var promise = new Promise(function(resolve, reject) {// XH ...

  6. 手写一个promise用法_手写一个Promise

    JS面向对象 在JS中一切皆对象,但JS并不是一种真正的面向对象(OOP)的语言,因为它缺少类(class)的概念.虽然ES6引入了class和extends,使我们能够轻易地实现类和继承.但JS并不 ...

  7. Chat Top10 | 给面试官手写一个 Nacos,多少 K?

    每周推荐的最新 Chat Top10 没有固定主题,仅仅是编辑部参考多方评分和反馈挑选出来的好文章,不一定适合你的口味,建议小心食用- 我们一起看下第三期 Chat Top10 都有哪些内容 ???? ...

  8. 深入Vue底层,手写一个vuex

    深入底层,手把手教你写一个Vuex 1. Vuex是什么?什么场景下使用? 2. Vuex的基本使用 3. 手写一个vuex 1. Vuex是什么?什么场景下使用? Vuex是vue的一个插件,叫做状 ...

  9. 手写一个自己的 cli 并发布到 npm 上

    手写一个自己的 cli 并发布到 npm 上 简介:大家平时肯定用过 vue-cli 或者 create-react-app,只需要敲简单的命令行,就可以生成一个完整的项目,非常好用.由于本人所在公司 ...

最新文章

  1. 卷积神经网络如何处理一维时间序列数据?
  2. linux mysql清除缓存_案例:通过shell脚本实现mysql数据备份与清理
  3. 武汉数字工程研究所计算机软件分数,武汉数字工程研究所2017考研成绩查询时间:2月16日...
  4. 如把联想电脑计算机图标放在桌面上,thinkpad电脑图标没了怎么恢复
  5. nginx php 源码安装,Nginx和php安装及配置一之编译安装nginx-1.8.0
  6. 【脑机接口】用人脑意念控制机器人即将落地
  7. sql数据库中有多列重复的数据查询
  8. C#用SqlCilent模式连接数据库实例
  9. 微信JS SDK Demo 官方案例
  10. 关于Redis的常识
  11. some tools
  12. 天猫手机一战成名? 塑造品牌 完胜京东
  13. 带本信息论看《三体》——信息论课程论文
  14. ruby 安装和使用
  15. hdu5956, The Elder (树型dp, 斜率优化)
  16. .NET/C# 阻止屏幕关闭,阻止系统进入睡眠状态
  17. 大数据开发hive数据库常用命令汇总
  18. 海淀服务器维修,服务器维修服务器维修防御升级、数据恢复、对接出错等维修服务...
  19. RocketMQ源码分析之request-reply特性
  20. 关系网络lbs的应用_LBS中国起步:探索空间关系的商业化

热门文章

  1. 计算机科学与技术审核评估专家,教育部本科教学审核评估专家喻祖国莅临我院开展深度访谈...
  2. 【循环链表】数据结构——单向循环链表和双向循环链表操作笔记
  3. java基础英语单词汇总,JAVA基础英语单词表(下)
  4. js获取元素高度比较
  5. 数字人相关的一些网站
  6. 记一次SQL server的驱动配置
  7. linux程序测试工具gprof,gprof-如何在Linux上分析多线程C ++应用程序?
  8. Tita绩效宝:80条有用的绩效考核评语
  9. 【嵌入式总复习】Linux管道详解——管道通信、无名管道、有名管道、具体应用示例
  10. 第四章:Python项目组织结构-第一节:包、模块以及__init__.py文件