关于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
好了这就搞定了,大功告成。