深入理解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] = 100 if (++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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值