实现promise
Promise是ES6中的新的异步语法,解决了回调嵌套的问题:
new Promise((resolve)=>{
setTimeout(()=>{
resolve(1)
},1000)
}).then(val =>{
console.log(val);
return new Promise((resolve)=>{
setTimeout(()=>{
resolve(2)
},1000)
})
}).then(val => {
console.log(val);
})
实现状态切换
- promise实例有三个状态,
pending,fulfilled,rejected - promise实例在构造是可以传入执行函数,执行函数有两个形参
resolve,reject可以改变promise的状态,promise的状态一旦改变后不可再进行改变。 - 执行函数会在创建promise实例时,同步执行
const PENDING = 'PENDING'; // 初始状态
const FULFILLED = 'FULFILLED'; // 成功状态
const REJECTED = 'REJECTED'; // 失败状态
class Promise2 {
constructor(executor){
this.status = PENDING
this.value = null
this.reason = null
const resolve = (value) => {
if (this.status === PENDING) {
this.value = value;
this.status = FULFILLED;
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.reason = reason;
this.status = REJECTED;
}
}
try {
executor(resolve,reject)
}catch (e) {
reject(e)
}
}
}
let p = new Promise2((resolve,reject)=>{resolve(1)})
实现then异步执行
promise实例可以调用then方法并且传入回调:
如果调用then时,Promise实例是fulfilled状态,则马上异步执行传入的回调。
如果调用then时,Promise实例是pending状态,传入的回调会等到resolve后再异步执行
例子:
let p = new Promise((resolve, reject)=>{
console.log(1);
resolve(2)
console.log(3);
})
p.then((val)=>{
console.log(val);
})
//1
//3
//2
let p = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve(1)
},2000)
})
p.then((val)=>{
console.log(val);
})
思路:需要用回调先保存到队列中,在resolve后异步执行队列里的回调,在then时判断实例的状态再决定是将回调推入队列,还是直接异步执行回调:
const PENDING = 'PENDING'; // 初始状态
const FULFILLED = 'FULFILLED'; // 成功状态
const REJECTED = 'REJECTED'; // 失败状态
class Promise2 {
constructor(executor){
this.status = PENDING
this.value = null
this.reason = null
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.status === PENDING) {
this.value = value;
this.status = FULFILLED;
setTimeout(()=>{
this.onFulfilledCallbacks.forEach(fn => fn(this.value));
})
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.reason = reason;
this.status = REJECTED;
setTimeout(()=>{
this.onFulfilledCallbacks.forEach(fn => fn(this.reason));
})
}
}
try {
executor(resolve,reject)
}catch (e) {
reject(e)
}
}
then(onFulfilled, onRejected) {
if (this.status === FULFILLED) {
setTimeout(()=>{
onFulfilled(this.value);
})
}
if (this.status === REJECTED) {
setTimeout(()=>{
onRejected(this.reason);
})
}
if (this.status === PENDING) {
this.onFulfilledCallbacks.push(onFulfilled); // 存储回调函数
this.onRejectedCallbacks.push(onRejected); // 存储回调函数
}
}
}
resolve Promise实例的情况
resolve的值有可能也是个promise实例,这时候就要用前述实例自己resolve的值
let p = new Promise((resolve,reject) =>{ //promise1
resolve(new Promise((resolve2,reject2)=>{ //promise2
setTimeout(()=>{
resolve2(1)
},1000)
}))
})
p.then((val)=>{
console.log(val);
})
因此需要在promise1的resolve函数中进行判断,是promise实例则在这个promise实例(promise2)后接一个then,并且将promise1的resolve作为回调传入promise2的then
const PENDING = 'PENDING'; // 初始状态
const FULFILLED = 'FULFILLED'; // 成功状态
const REJECTED = 'REJECTED'; // 失败状态
class Promise2 {
constructor(executor){
this.status = PENDING
this.value = null
this.reason = null
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (value instanceof this.constructor) {
value.then(resolve, reject); //resolve reject是箭头函数,this已经绑定到外层Promise
return
}
if (this.status === PENDING) {
this.value = value;
this.status = FULFILLED;
setTimeout(()=>{
this.onFulfilledCallbacks.forEach(fn => fn(this.value));
})
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.reason = reason;
this.status = REJECTED;
setTimeout(()=>{
this.onFulfilledCallbacks.forEach(fn => fn(this.reason));
})
}
}
try {
executor(resolve,reject)
}catch (e) {
reject(e)
}
}
then(onFulfilled, onRejected) {
if (this.status === FULFILLED) {
setTimeout(()=>{
onFulfilled(this.value);
})
}
if (this.status === REJECTED) {
setTimeout(()=>{
onRejected(this.reason);
})
}
if (this.status === PENDING) {
this.onFulfilledCallbacks.push(onFulfilled); // 存储回调函数
this.onRejectedCallbacks.push(onRejected); // 存储回调函数
}
}
}
let p = new Promise2((resolve,reject) =>{
resolve(new Promise2((resolve2,reject2)=>{
setTimeout(()=>{
resolve2(1)
},1000)
}))
})
p.then((val)=>{
console.log(val);
})
实现链式调用
then可以链式调用,而且前一个then的回调的返回值,如果不是promise实例,则下一个then回调的传参值就是上一个then回调的返回值,如果是promise实例,则下一个then回调的传参值,是上一个then回调返回的promise实例的解决值(value)
let p = new Promise((resolve,reject) =>{
setTimeout(()=>{
resolve(1)
},1000)
})
p.then(val => {
console.log(val);
return new Promise((resolve) => {
setTimeout(()=>{
resolve(2)
},1000)
})
}).then(val => {
console.log(val);
return 3
}).then(val => {
console.log(val);
})
既然能够链式调用,那么then方法本身的返回值必定是一个Promise实例。那么返回的promise实例是不是自身呢?答案显而易见:不是。如果一个promise的then方法的返回值是promise自身,在new一个Promise时,调用了resolve方法,因为promise的状态一旦更改便不能再次更改,那么下面的所有then便只能执行成功的回调,无法进行错误处理,这显然并不符合promise的规范和设计promise的初衷。
因此 then方法会返回一个新的promise实例
const PENDING = 'PENDING'; // 初始状态
const FULFILLED = 'FULFILLED'; // 成功状态
const REJECTED = 'REJECTED'; // 失败状态
class Promise2 {
constructor(executor){
this.status = PENDING
this.value = null
this.reason = null
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (value instanceof this.constructor) {
value.then(resolve, reject); //resolve reject是箭头函数,this已经绑定到外层Promise
return
}
if (this.status === PENDING) {
this.value = value;
this.status = FULFILLED;
setTimeout(()=>{
this.onFulfilledCallbacks.forEach(fn => fn(this.value));
})
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.reason = reason;
this.status = REJECTED;
setTimeout(()=>{
this.onFulfilledCallbacks.forEach(fn => fn(this.reason));
})
}
}
try {
executor(resolve,reject)
}catch (e) {
reject(e)
}
}
then(onFulfilled, onRejected) {
const promise2 = new this.constructor((resolve, reject) => { // 待返回的新的promise实例
if (this.status === FULFILLED) {
setTimeout(()=>{
try {
let callbackValue = onFulfilled(this.value);
resolve(callbackValue);
}catch(error) {
reject(error) // 如果出错此次的then方法的回调函数出错,在将错误传递给promise2
}
})
}
if (this.status === REJECTED) {
setTimeout(()=>{
try {
let callbackValue= onRejected(this.reason);
resolve(callbackValue);
} catch (error) {
reject(error);
}
})
}
if (this.status === PENDING) {
this.onFulfilledCallbacks.push(() => {
try {
let callbackValue = onFulfilled(this.value);
resolve(callbackValue);
}catch (error) {
reject(error)
}
});
this.onRejectedCallbacks.push(() => {
try {
let callbackValue = onRejected(this.reason);
resolve(callbackValue);
} catch (error) {
reject(error);
}
});
}
})
return promise2;
}
}
实现其他方法
- catch
- resolve
- reject
- all
- race
方法演示:
/*catch方法*/
let p = new Promise((resolve, reject) => {
reject(1)
})
p.catch(reason => {
console.log(reason);
})
/*Promise.resolve*/
let p = Promise.resolve(1)
/*Promise.resolve*/
let p = Promise.reject(1)
/*Promise.all*/
let p = Promise.all([
new Promise(resolve => {
setTimeout(() => {
resolve(1)
}, 1000)
}),
new Promise(resolve => {
setTimeout(() => {
resolve(2)
}, 2000)
}),
new Promise(resolve => {
setTimeout(() => {
resolve(3)
}, 3000)
}),
])
p.then(val => {
console.log(val);
})
/*Promise.race*/
let p = Promise.race([
new Promise(resolve => {
setTimeout(() => {
resolve(1)
}, 1000)
}),
new Promise(resolve => {
setTimeout(() => {
resolve(2)
}, 2000)
}),
new Promise(resolve => {
setTimeout(() => {
resolve(3)
}, 3000)
}),
])
p.then(val => {
console.log(val);
})
const PENDING = 'PENDING'; // 初始状态
const FULFILLED = 'FULFILLED'; // 成功状态
const REJECTED = 'REJECTED'; // 失败状态
class Promise2 {
static resolve(value) {
if (value instanceof this) {
return value;
}
return new this((resolve, reject) => {
resolve(value);
});
};
static reject(reason) {
return new this((resolve, reject) => reject(reason))
};
static all(promises){
return new this((resolve, reject) => {
let resolvedCounter = 0;
let promiseNum = promises.length;
let resolvedValues = new Array(promiseNum);
for (let i = 0; i < promiseNum; i += 1) {
Promise2.resolve(promises[i]).then(
value => {
resolvedCounter++;
resolvedValues[i] = value;
if (resolvedCounter === promiseNum) {
return resolve(resolvedValues);
}
},
reason => {
return reject(reason);
},
);
}
});
};
static race(promises){
return new this((resolve, reject) => {
if (promises.length === 0) {
return;
} else {
for (let i = 0, l = promises.length; i < l; i += 1) {
Promise2.resolve(promises[i]).then(
data => {
resolve(data);
return;
},
err => {
reject(err);
return;
},
);
}
}
});
}
constructor(executor) {
this.status = PENDING
this.value = null
this.reason = null
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (value instanceof this.constructor) {
value.then(resolve, reject); //resolve reject是箭头函数,this已经绑定到外层Promise
return
}
if (this.status === PENDING) {
this.value = value;
this.status = FULFILLED;
setTimeout(() => {
this.onFulfilledCallbacks.forEach(fn => fn(this.value));
})
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.reason = reason;
this.status = REJECTED;
setTimeout(() => {
this.onFulfilledCallbacks.forEach(fn => fn(this.reason));
})
}
}
try {
executor(resolve, reject)
} catch (e) {
reject(e)
}
}
then(onFulfilled, onRejected) {
const promise2 = new this.constructor((resolve, reject) => { // 待返回的新的promise实例
if (this.status === FULFILLED) {
setTimeout(() => {
try {
let callbackValue = onFulfilled(this.value);
resolve(callbackValue);
} catch (error) {
reject(error) // 如果出错此次的then方法的回调函数出错,在将错误传递给promise2
}
})
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolve(x);
} catch (error) {
reject(error);
}
})
}
if (this.status === PENDING) {
this.onFulfilledCallbacks.push(() => {
try {
let callbackValue = onFulfilled(this.value);
resolve(callbackValue);
} catch (error) {
reject(error)
}
});
this.onRejectedCallbacks.push(() => {
try {
let callbackValue = onRejected(this.reason);
resolve(callbackValue);
} catch (error) {
reject(error);
}
});
}
})
return promise2;
}
catch(onRejected) {
return this.then(null, onRejected);
}
}