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

  关于Promise函数可以参考我写的这篇文章https://www.cnblogs.com/qiaohong/p/7705262.html,我们现在就深入理解一下这个函数。

  首先说下Promise方法,Promise方法中还是有些是比较好用的,比如说Promise.all()方法(Promise.all()方法的参数是一个数组,会按照数组的结果放到成功的回调里,如果有一个错误那么就不会成功)、Promise.race()方法(这个方法的参数也是一个数组,Promise.race()会同时发起并发,但是以返回最快的结果为结果,可以用于多台服务器并发的时候用)。代码参考如下

  

let promise = new Promise()
let fs = require('mz/fs');    //使用了一个mz的包  mz封装了fs对应的函数,并改为Promise
promise.race([fs.readFile('./name.txt', 'utf8'), fs.readFile('./age.txt', 'utf8')]).then((data) => {console.log(data);
}, err => {console.log(err);
});

  如何手写Promise a+规范的Promise呢?跟我一步步来,坐稳,看完了你也就懂了。

  先想Pormise的特点:  

  1.每次promise执行then后都会返回一个新的promise
  2.如果then中返回的是一个结果的话会把这个结果传递下一次then中的成功回调
  3.如果then中出现异常 会走下一个then的失败 将错误传递到失败中
  4.如果失败后还可以成功,如果返回undefined 会把undefined 传递给下一次
  5.catch 会捕获到没有捕获的异常
  6.成功或者失败是一个可选参数
  7. 如果then方法返回的是一个promise 那么会等待这个promise执行完决定返回的那个promise是成功还是失败
  8.为什么要返回一个新的promise而不是this promise状态确定后 就是不能更改。

  说干就干,拿起键盘就是怼

  

function Promise(executor) {let self = this;self.status = 'pending';  //promise默认就是等待状态self.value = undefined;   //存放成功回调的值self.reason = undefined;  //存放失败回调的值self.onResolved = [];  //专门存放成功的回调函数self.onRejected = [];  //存放失败的回调函数
function resolve(value) {  //promise成功走这个函数if (self.status === 'pending') {self.value = value;self.status = 'resolved';self.onResolved.forEach(fn => fn());}}function reject(reason) {  //promise失败走这个函数if (self.status === 'pending') {self.reason = reason;self.status = 'rejected';self.onRejected.forEach(fn => fn());}}try {executor(resolve, reject);} catch (e) {reject(e);}
}
//确定then里面的成功/失败函数执行的结果和返回的promise2是什么关系
//ps:promise a+里面确实有很多的槽点  比如这个x、y和promise2什么的都是那里面规定的
function resolvePromise(promise2, x, resolve, reject) {if (promise2 === x) {return reject(new TypeError('循环引用'));}let called;if (x != null && (typeof x === 'object' || typeof x === 'function')) {try {let then = x.then; // 如何判断是promise 就判断又没then方法 if (typeof then === 'function') {then.call(x, (y) => {if (called) return;called = true;resolvePromise(promise2, y, resolve, reject);}, (e) => {if (called) return;called = true;reject(e);});} else {resolve(x);}} catch (e) {if (called) return;called = true;reject(e);}} else {resolve(x);}
}//promise的then方法
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;  //返回新的promise就是promise2  不要问我为什么 a+里面规范的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); // 解析x 和 promise2的关系} catch (e) {reject(e);}}, 0);}if (self.status === 'pending') {self.onResolved.push(function () {setTimeout(() => {try {let x = onfulfilled(self.value);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0);});self.onRejected.push(function () {setTimeout(() => {try {let x = onrejected(self.reason);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0);});}})return promise2;
}//实现promise原生方法
Promise.all = function (promises) {return new Promise((resolve, reject) => {let results = [];    let i = 0;function processData(index, data) {results[index] = data; // let arr = []  arr[2] = 100if (++i === promises.length) {resolve(results);}}for (let i = 0; i < promises.length; i++) {let p = promises[i];p.then((data) => { // 成功后把结果和当前索引 关联起来
        processData(i, data);}, reject);}})
}
Promise.race = function (promises) {return new Promise((resolve, reject) => {for (let i = 0; i < promises.length; i++) {let p = promises[i];p.then(resolve, reject);}})
}
Promise.prototype.catch = function (onrejected) {return this.then(null, onrejected)
}
Promise.reject = function (reason) {return new Promise((resolve, reject) => {reject(reason)})
}
Promise.resolve = function (value) {return new Promise((resolve, reject) => {resolve(value);})
}

 // 测试代码是否符合a+ 规范 为了让其能测试
 // npm install promises-aplus-tests -g
 // promises-aplus-tests 文件名 可以测试

Promise.defer = Promise.deferred = function () {let dfd = {};dfd.promise = new Promise((resolve, reject) => {dfd.resolve = resolve;dfd.reject = reject;});return dfd;
}
module.exports = Promise

  好了这就搞定了,大功告成。

  

posted on 2018-09-01 21:23 另一种失败 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/qiaohong/p/9571687.html

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

  1. 写一个符合 Promises/A+ 规范并可配合 ES7 async/await 使用的 Promise

    原文地址 从历史的进程来看,Javascript 异步操作的基本单位已经从 callback 转换到 Promise.除了在特殊场景使用 stream,RxJs 等更加抽象和高级的异步数据获取和操作流 ...

  2. 一步步写一个符合Promise/A+规范的库

    Promise本意是承诺,在程序中的意思就是承诺我过一段时间后会给你一个结果. ES6 中采用了 Promise/A+ 规范,Promise 实现之前,当然要先了解 Promise/A+ 规范,规范地 ...

  3. 一步步写一个符合Promise/A+规范的库 1

    Promise本意是承诺,在程序中的意思就是承诺我过一段时间后会给你一个结果. ES6 中采用了 Promise/A+ 规范,Promise 实现之前,当然要先了解 Promise/A+ 规范,规范地 ...

  4. python软件代码示例-用Python写一个模拟qq聊天小程序的代码实例

    Python 超简单的聊天程序 客户端: import socket, sys host = '10.248.27.23' # host = raw_input("Plz imput des ...

  5. python播放wav文件_python3 写一个WAV音频文件播放器的代码

    环境:ubuntu 16.04 python3.5 pycharm 包 : wave pyaudio sys 上代码:AudioPlayer.py # coding:utf-8 # author:ki ...

  6. 能不能用python开发qq_用Python写一个模拟qq聊天小程序的代码实例

    用Python写一个模拟qq聊天小程序的代码实例 发布时间:2020-09-09 07:49:29

  7. 用Python写一个模拟qq聊天小程序的代码实例

    前言 今天小编就为大家分享一篇关于用Python写一个模拟qq聊天小程序的代码实例,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧 Python 超简单的聊天 ...

  8. 【Python】原创 | 写一个符合人类思维的四舍五入函数(No round !!!)

    前言 众所周知,python中的round采取的是银行家舍入.而不是四舍五入. # python中采取的规则是 <银行家式舍入法> # 即 四舍六入五成双 # 详细解释见下 ''' 四舍六 ...

  9. 写一个画螺旋旋转的花朵python代码

    这是一个画螺旋旋转的花朵的代码示例: import turtle# 设置画布 turtle.setup(800, 600) turtle.screensize(800, 600) turtle.tit ...

最新文章

  1. Android RxJava 2.0中backpressure(背压)概念的理解
  2. Java中 SPI的使用
  3. iOS开发之检查更新
  4. AttributeError: module 'pymongo' has no attribute 'Connection'
  5. java filefilter的用法_Java File.listFiles(FileFilter filter)方法
  6. JPA Annotation注解
  7. ubuntu 18.04使用sysbench测试MySQL性能
  8. git下载及安装向导如何配置
  9. 如何设置静态内容缓存时间
  10. pdf页眉页脚设置步骤
  11. SQL常用语句总结整理
  12. SCI收录的期刊查询
  13. Qt之时间轴样式汇总
  14. Xshell国内免费下载
  15. AWD比赛入门攻略总结
  16. linux如何启动一个进程而不阻塞,当你在 Linux 上启动一个进程时会发生什么? | Linux 中国...
  17. html网页改兼容模型,让DIV+CSS兼容所有浏览器
  18. 传感器的灵敏度 分辨率与分辨力和精度 + 光纤光缆
  19. oracle数据库left用法,ORACLE 左联接 left join
  20. 在使用增强for循环的时候对遍历的集合进下remove操作报错java.util.ConcurrentModificationException

热门文章

  1. 记一篇IT培训日记046-瞎想
  2. Nmap网络扫描器实验
  3. 数独快速随机出题的算法
  4. java中trim()方法是用来干什么的?
  5. 心理咨询APP开发-心理咨询平台-心理咨询系统源码
  6. cdr 表格自动填充文字_活久见!Excel里输入文字,还能这样做?!
  7. 众昂矿业架构师刘金海:锂电级PVDF逐渐成为需求主力,拉动萤石增长
  8. excel中 时分秒格式相加
  9. java算狗年龄,如何判断狗狗的年龄?学会这几招,就能看出狗狗的真实年龄
  10. 天天模拟器ADB调试APK