1、基础框架
promiser的构造函数接收一个参数是executor函数,并且传入两个参数:resolve,reject。分别是异步操作成功的回调函数和异步操作失败后的回调函数。
promise有三个状态 等待(pending) 成功态 (fulfilled) 失败态(rejected)
默认情况是 pending -> fulfilled
pending -> rejected
fulfilled不能和rejected相互转化复制代码
下面来看一下代码具体的实现:
function Promise(executor){
let self = this;
self.status = 'pending'
self.value = undefined;
self.reason = undefined;
self.onResolvedCallbacks = []; //异步时,存放成功的回调函数
self.onRejectedCallbacks = []; //异步时,存放失败的回调函数
// 只有状态是pending 参能进行状态的转化
function resolve(value) {
if(self.status === 'pending'){
self.value = value;
self.status = 'fulfilled';
self.onResolvedCallbacks.forEach(function (fn) {
fn(); //成功时调用循环调用成功的函数执行
});
}
}
function reject(reason) {
if(self.status === 'pending'){
self.reason = reason;
self.status = 'rejected';
self.onRejectedCallbacks.forEach(function (fn) {
fn();//失败时调用循环调用失败的函数执行
})
}
}
try{
executor(resolve, reject); // 如果执行这个executor执行时候抛出异常 应该走下一个then的失败
}catch(e){
reject(e);// 出错了
}
}复制代码
2、then方法
每个promise实例上都有一个then方法,then方法接受两个参数,onFulfilled和onRejected。判断状态成功的时候(fulfilled),调用onFulfilled函数,把成功的值传回。判断状态失败的时候(rejected),调用onRejected失败函数,把失败的值传回。
如果状态是pending,代表是异步执行,把onFulfilled和onRejected函数存起来,executor里resolve函数和reject函数执行的时候再调用。
Promise.prototype.then = function (onFulfilled, onRejected) {
let self = this;
if (self.status === 'fulfilled'){
onFulfilled(self.value);
}
if (self.status === 'rejected'){
onRejected(self.reason);
}
if( self.status === 'pending'){
//异步的实现
self.onResolvedCallbacks.push(function () {
onFulfilled(self.value);
});
self.onRejectedCallbacks.push(function () {
onRejected(self.reason);
})
}}
复制代码
3、then方法链式调用
- promise每次调用then后,返回一个新的promise(then方法成功后 返回的是一个新的promise,这个返回的promise会被执行,如果返回的promise是成功的,会把这个结果传递到外层的下一个then中)
- 如果返回的是promise 用promise的成功或者失败 执行下一个then
- 如果返回的是一个普通值 会走外层下一个then的成功
- 如果执行的时候 抛出异常就会走到下一个次then中的失败
- then中可以不传递参数,如果不传递 会透到下一个then中
Promise.prototype.then = function (onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled:function (data) { return data }
onRejected = typeof onRejected === 'function' ? onRejected:function (err) { throw err; }
let self = this;
let promise2; //promise2就是我们每次调用then后返回的新的promise
promise2 = new Promise(function (resolve,reject) {
if (self.status === 'fulfilled') {
// 这个返回值是成功函数的执行结果
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);
}catch(e){
reject(e)
}
},0)
}
if (self.status === 'pending') {
// 默认当前 new Promise executor中是有异步的
self.onResolvedCallbacks.push(function () {
setTimeout(() => {
try{
let x = onFulfilled(self.value);
resolvePromise(promise2, x, resolve, reject);
}catch(e){
reject(e)
}
}, 0);
});
self.onRejectedCallbacks.push(function () {
setTimeout(() => {
try{
let x = onRejected(self.reason);
resolvePromise(promise2, x, resolve, reject);
}catch(e){
reject(e);
}
}, 0);
})
}
});
return promise2;
}复制代码
4、链式调用的核心方法
核心方法,处理成功或者失败执行的返回值和promise2的关系
function resolvePromise(promise2,x,resolve,reject) {
// 这个处理函数 需要处理的逻辑韩式很复杂的
// 有可能这个x 是一个promise 但是这个promise并不是我自己的
if(promise2 === x){
return reject(new TypeError('TypeError: Chaining cycle detected for promise #<Promise>'))
}
// 不单单需要考虑自己 还要考虑 有可能是别人的promise let called;
// 文档要求 一旦成功了 不能调用失败
if((x!=null&&typeof x=== 'object') || typeof x === 'function'){
// 这样只能说 x 可能是一个promise
try{
// x = {then:function(){}}
let then = x.then; // 取then方法
if(typeof then === 'function'){
then.call(x,function (y) {
// resolve(new Promise)
if(!called){called = true;} else{ return;}
resolvePromise(x,y,resolve,reject); // 递归检查promise
},function (r) {
if (!called) { called = true; } else { return; }
reject(r);
});
}else{ // then方法不存在
resolve(x); // 普通值
}
}catch(e){ // 如果取then方法出错了,就走失败
if (!called) { called = true; } else { return; }
reject(e);
}
}else{
resolve(x);
}
}复制代码
5、catch方法的实现
catch方法其实就是then方法,直接调用then方法,成功传null,失败把参数传进去就ok了。
Promise.prototype.catch = function (onRejected) {
return this.then(null, onRejected);
}复制代码
6、finally方法
无论成功还是失败,都要执行回调函数,并且把成功或者失败的值向下传递。
Promise.prototype.finally = function (cb) {
return this.then(function (data) {
cb();
return data;
}, function (err) {
cb();
throw err;
});
}复制代码
7、reject方法实现
Promise.reject = function (reason) {
return new Promise(function (resolve, reject) {
reject(reason);
})
}复制代码
8、resolve方法实现
Promise.resolve = function (value) {
return new Promise(function (resolve, reject) {
resolve(value);
})
}复制代码
9、all方法实现
Promise提供了一个 并发的方法 Promise.all 实现并发执行promise.all方法返回的结果是一个promise
Promise.all = function (promises) {
return new Promise(function (resolve, reject) {
let arr = []; // 处理数据的方法
let i = 0;
function processData(index, data) {
arr[index] = data; //数组的索引和长度的关系
if (++i === promises.length) {
// 当数组的长度 和promise的个数相等时 说明所有的promise都执行完成了
resolve(arr);
}
}
for (let i = 0; i < promises.length; i++) {
let promise = promises[i];
if (typeof promise.then == 'function') {
promise.then(function (data) {
processData(i, data); // 把索引和数据 对应起来 方便使用
}, reject)
} else {
processData(i, promise);
}
}
});
}复制代码
10、race方法实现
Promise.race传一个数组过去,只返回一个结果,哪个快返回哪个。
Promise.race = function (promises) {
return new Promise(function (resolve, reject) {
for (let i = 0; i < promises.length; i++) {
let promise = promises[i];
if (typeof promise.then == 'function') {
promise.then(resolve, reject)
} else {
resolve(promise);
}
}
})
}复制代码