写一个Promises来实现Promise功能,当执行resolve()会改变状态,执行then
const PENDING = 'pending';//进行中
const FULFILLED = 'fulfilled';//成功
const REJECTED = 'rejected';//失败
function Promises(executor) {
let self = this;
self.status = PENDING;
function resolve(value) {
if (self.status === PENDING) {
self.status = FULFILLED;//当执行resovle改变状态
self.value = value;
}
}
function reject(reason) {
if (self.status === PENDING) {
self.status = REJECTED;//当执行reason改变状态
self.reason = reason;
}
}
try {
executor(resolve, reject);//把改变状态的函数传到函数
} catch (e) {//当报错会直接执行reject()改变状态
reject(e);
}
}
Promises.prototype.then=function(onFulfilled,onRejected){
onFulfilled=typeof onFulfilled==='function'?onFulfilled: value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
let self=this;
let Promises2=new Promises(function(resolve,reject){
if(self.status===FULFILLED){
onFulfilled(self.value);//接受状态函数里的返回值
}
})
return Promises2;
}
window.Promises = Promises;
原理就是我们在new Promises(function(resolve,reject){ 调用resolve()时,会让Promises状态改变为FULFILLED 这时候then的第一个参数就会触发
var arr=new Promises(function(resolve,reject){
console.log(123)//123//先执行这个
resolve();
});
arr.then(function(value){
console.log(123)//123
})
但是会有问题,看下面代码,因为定时器是异步的当执行到then的时候这时resolve()还没执行,这时的状态还是PENDING,当resolve执行的时候这时代码状态虽然改变了但是self.status已经获取过了,不会执行then
var arr=new Promises(function(resolve,reject){
setTimeout(function(){//因为定时器是异步的当
resolve();
},10000)
});
arr.then(function(value){
console.log(123)//不会执行then
})
改进代码如下 因为定时器是几秒后执行,这时状态是PENDING,我们把then里的回调push到self.onFulfilled里,当定时器执行完的时候触发resolve()就会把self.onFulfilled里存的then回调函数执行
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
function Promises(executor) {
let self = this;
self.status = PENDING;
self.onFulfilled = [];//成功的回调
self.onRejected = []; //失败的回调
//PromiseA+ 2.1
function resolve(value) {
if (self.status === PENDING) {
self.status = FULFILLED;
self.value = value;
self.onFulfilled.forEach(fn => fn());//PromiseA+ 2.2.6.1
}
}
function reject(reason) {
if (self.status === PENDING) {
self.status = REJECTED;
self.reason = reason;
self.onRejected.forEach(fn => fn());//PromiseA+ 2.2.6.2
}
}
try{
executor(resolve,reject);
} catch (e) {
reject(e);
}
}
Promises.prototype.then=function(onFulfilled,onRejected){
onFulfilled=typeof onFulfilled==='function'?onFulfilled: value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
let self=this;
let Promises2=new Promises(function(resolve,reject){
console.log(self.status)
if(self.status===FULFILLED){
try {
onFulfilled(self.value);
} catch (e) {
reject(e);
}
}else if(self.status === REJECTED){
try {
onRejected(self.reason);
} catch (e) {
reject(e);
}
}else if (self.status === PENDING){
self.onFulfilled.push(() => {
try {
onFulfilled(self.value)
} catch (e) {
reject(e);
}
});
self.onRejected.push(() => {
try {
onRejected(self.reason);
} catch (e) {
reject(e);
}
});
}
})
return Promises2;
}
这里我们还没实现链式操作,虽然then里new 了一个新的Promises对象,但是他的状态没有被改变,需要在内部用resolvePromise改变,当第一个Promises对象状态是fulfilled那么后面then创建的对象的状态都是'fulfilled'那么链式操作的then的第一参数函数都能执行,还需要解决当then return的是Promises对象的情况
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
function Promises(executor) {
let self = this;
self.status = PENDING;
self.onFulfilled = [];//成功的回调
self.onRejected = []; //失败的回调
//PromiseA+ 2.1
function resolve(value) {
if (self.status === PENDING) {
self.status = FULFILLED;
self.value = value;
self.onFulfilled.forEach(fn => fn());//PromiseA+ 2.2.6.1
}
}
function reject(reason) {
if (self.status === PENDING) {
self.status = REJECTED;
self.reason = reason;
self.onRejected.forEach(fn => fn());//PromiseA+ 2.2.6.2
}
}
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
Promises.prototype.then = function (onFulfilled, onRejected) {
//PromiseA+ 2.2.1 / PromiseA+ 2.2.5 / PromiseA+ 2.2.7.3 / PromiseA+ 2.2.7.4
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
let self = this;
//PromiseA+ 2.2.7
let promise2 = new Promises((resolve, reject) => {
console.log(self.status)
if (self.status === FULFILLED) {
//PromiseA+ 2.2.2
//PromiseA+ 2.2.4 --- setTimeout
setTimeout(() => {
try {
//PromiseA+ 2.2.7.1
let x = onFulfilled(self.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
//PromiseA+ 2.2.7.2
reject(e);
}
});
} else if (self.status === REJECTED) {
//PromiseA+ 2.2.3
setTimeout(() => {
try {
let x = onRejected(self.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
} else if (self.status === PENDING) {
self.onFulfilled.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(self.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
self.onRejected.push(() => {
setTimeout(() => {
try {
let x = onRejected(self.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
});
return promise2;
}
function resolvePromise(promise2, x, resolve, reject) {
let self = this;
//PromiseA+ 2.3.1
if (promise2 === x) {
reject(new TypeError('Chaining cycle'));
}
if (x && typeof x === 'object' || typeof x === 'function') {
let used; //PromiseA+2.3.3.3.3 只能调用一次
try {
let then = x.then;
console.log(then)
if (typeof then === 'function') {
//PromiseA+2.3.3
then.call(x, (y) => {
//PromiseA+2.3.3.1
if (used) return;
used = true;
resolvePromise(promise2, y, resolve, reject);
}, (r) => {
//PromiseA+2.3.3.2
if (used) return;
used = true;
reject(r);
});
}else{
//PromiseA+2.3.3.4
if (used) return;
used = true;
resolve(x);
}
} catch (e) {
//PromiseA+ 2.3.3.2
if (used) return;
used = true;
reject(e);
}
} else {
//PromiseA+ 2.3.3.4
resolve(x);
}
}
window.Promises=Promises;
当出现then return的是Promises对象的时候,这个时候把return的Promises对象给resolvePromise函数处理,resolvePromise会在内部调用创建的新的Promises对象then方法,如果在新Promises对象里面调用resolve()方法,那么新的对象的then方法内部创建的Promises会被resolvePromise里调用resolve()使状态发生改变,就能实现替换最初的then创建的对象,实现链式操作
var arr=new Promises(function(resolve,reject){
resolve();
});
arr.then(function(value){
return new Promises(function(resolve,reject){//如果return对象会在内部调用then方法
resolve(123)//调用resolve()方法,会调用then的第一个参数resolvePromise,会让调用then创建的对象的状态变为'fulfilled'
console.log(111111)
})
}).then(function(value){//那么后面调用then方法就能执行
console.log(value)
})
接下来实现catch和finally功能
Promise.prototype.catch
用于指定出错时的回调,是特殊的then方法,catch之后,可以继续 .then
Promise.prototype.finally
不管成功还是失败,都会走到finally中,并且finally之后,还可以继续then。并且会将值原封不动的传递给后面的then.
Promise.prototype.catch = function (onRejected) {
return this.then(null, onRejected);
}
Promise.prototype.finally = function (callback) {
return this.then((value) => {
return Promise.resolve(callback()).then(() => {
return value;
});
}, (err) => {
return Promise.resolve(callback()).then(() => {
throw err;
});
});
}
Promise.all
Promise.all = function (promises) {
return new Promise((resolve, reject) => {
let index = 0;
let result = [];
if (promises.length === 0) {
resolve(result);
} else {
function processValue(i, data) {
result[i] = data;
if (++index === promises.length) {
resolve(result);
}
}
for (let i = 0; i < promises.length; i++) {
//promises[i] 可能是普通值
Promise.resolve(promises[i]).then((data) => {
processValue(i, data);
}, (err) => {
reject(err);
return;
});
}
}
});
}
Promise.race
Promise.race函数返回一个 Promise,它将与第一个传递的 promise 相同的完成方式被完成。它可以是完成( resolves),也可以是失败(rejects),这要取决于第一个完成的方式是两个中的哪个。 如果传的参数数组是空,则返回的 promise 将永远等待。 如果迭代包含一个或多个非承诺值和/或已解决/拒绝的承诺,则 Promise.race 将解析为迭代中找到的第一个值。
Promise.race = function (promises) {
return new Promise((resolve, reject) => {
if (promises.length === 0) {
return;
} else {
for (let i = 0; i < promises.length; i++) {
Promise.resolve(promises[i]).then((data) => {
resolve(data);
return;
}, (err) => {
reject(err);
return;
});
}
}
});
}
代码原作者: 作者:刘小夕 链接:segmentfault.com/a/119000001…