let p = new Promise ((resolve,reject)=>{
resolve('success');
reject('fail');
})
p.then(data=>{},fail=>{})
根据上述Promise的基本使用,分析:
- Promise是一个构造函数
- Promise接收一个立即执行的函数,且这个函数有两个参数,分别为resolve和reject
- Promise有3中状态pending、fulfilled、rejected
- resolve函数是将状态由pending改为fulfilled,reject函数是将状态由pending 改为rejected,且状态一旦变为fulfilled或者rejected就不能再更改状态了
- then方法接收两个函数参数,成功执行第一个,失败执行第二个,且要将成功(resolve)、失败(reject)的参数传入相应的函数中
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
class myPromise{
constructor(execute){
execute(this.resolve,this.reject)
}
status = PENDING;
successParams = undefined;
failParams = undefined;
resolve = (value)=>{
if(this.status !== PENDING) return;
this.status = FULFILLED;
this.successParams = value;
}
reject = (error)=>{
if(this.status !== PENDING) return;
this.status = REJECTED;
this.failParams = error;
}
then = (successCallback,failCallback)=>{
if(this.status === FULFILLED){
successCallback(this.successParams)
}
if(this.status === REJECTED){
failCallback(this.failParams)
}
}
}
如果Promise立即执行函数中有一个异步的方法,那么then函数没法立即执行,见下面:
let p = new myPromise((resolve,reject)=>{
setTimeout(()=>{
resolve('sucess');
},2000);
})
解决方法:将then函数的两个方法存储起来,等resolve或者reject之后再执行
class myPromise{
...
successCallback = undefined;
failCallback = undefined;
resolve = (value)=>{
...
this.successCallback && this.successCallback(value);
}
reject = (error)=>{
...
this.failCallback && this.failCallback(error)
}
then = (successCallback,failCallback)=>{
...
if(this.status === PENDING){
this.successCallback = successCallback;
this.failCallback = failCallback;
}
}
}
Promise 还可以同时调用多个then方法,如:
p.then(data=>{
console.log(1)
console.log(data)
},error=>{
console.log(error)
})
p.then(data=>{
console.log(2)
console.log(data)
},error=>{
console.log(error)
})
思路:(如果Promise立即执行函数中是同步不需要改变,如果是异步需要改变)
将then中的两个函数用数组存储起来,等到resolve、reject后依次执行
class myPromise{
...
successCallback = [];
failCallback = [];
resolve = (value)=>{
...
//this.successCallback && this.successCallback(value);
while(this.successCallback.length) this.successCallback.shift()(value)
}
reject = (error)=>{
...
// this.failCallback && this.failCallback(error)
while(this.failCallback.length) this.failCallback.shift()(error)
}
then = (successCallback,failCallback)=>{
...
if(this.status === PENDING){
this.successCallback.push(successCallback);
this.failCallback.push(failCallback);
}
}
}
Promise链式调用
p.then(data=>{
console.log(data)
return 100
}).then(data1=>{
console.log(111)
console.log(data1)
})
同步思路:
- then返回的要是一个Promise对象,这样才能继续调用then
- 上一个then的返回值给下一个then使用
class myPromise{
...
then = (successCallback,failCallback)=>{
let p2 = new myPromise((resolve)=>{
if(this.status === FULFILLED){
let x = successCallback(this.successParams);
resolve(x)
}
if(this.status === REJECTED){
failCallback(this.failParams)
}
if(this.status === PENDING){
this.successCallback.push(successCallback);
this.failCallback.push(failCallback);
}
})
return p2;
}
}
Promise then第一个函数返回有可能是普通参数,也有可能是Promise对象(同步)
function testPromise(){
return new MyPromise((resolve,reject)=>{
resolve(2)
})
}
p.then(data=>{
console.log(data)
return testPromise()
}).then(data1=>{
console.log(111)
console.log(data1)
})
思路:
- 如果返回的是普通参数,直接返回给下一个then使用
- 如果返回的是一个Promise对象,将成功的参数返回给下一个then的第一个函数使用,失败的参数返回给第二个函数使用
class MyPromise{
...
then = (successCallback,failCallback)=>{
let p2 = new MyPromise((resolve,reject)=>{
if(this.status === FULFILLED){
let x = successCallback(this.successParams);
promiseResolve(x,resolve,reject)
}
...
})
return p2;
}
}
function promiseResolve(x,resolve,reject){
if(x instanceof MyPromise){
x.then(resolve,reject)
}else{
resolve(x)
}
}
Promise then(第一个函数) 不能返回当前的这个Promise对象:
let p1 = p.then(data=>{
console.log(data)
return p1
})
思路:比对then返回的Promise和当前的promise对象,如果一样就抛错
class MyPromise{
...
then = (successCallback,failCallback)=>{
let p2 = new MyPromise((resolve,reject)=>{
if(this.status === FULFILLED){
setTimeout(()=>{
let x = successCallback(this.successParams);
promiseResolve(p2,x,resolve,reject)
},0);
}
...
})
return p2;
}
}
function promiseResolve(p,x,resolve,reject){
if(p === x){
return reject(new TypeError('error'))
}
...
}
遇到两个坑,1.必须加setTimeout,否则拿不到当前的Promise对象p2和then返回的当前Promise对象;2.在使用的时候,不能then去链式调用,这样两个Promise就不一样,没法比较了,见下面
错误的写法:
p.then(data=>{
console.log(data)
return p1
}).then(data1=>{
console.log(111)
},reason=>{
console.log(reason)
})
正确的写法:
let p1 = p.then(data=>{
console.log(data)
return p1
})
p1.then(data1=>{
console.log(111)
},reason=>{
console.log(reason)
})
捕获Promise中的错误
思路:promise中的错误来源
- Promise立即执行函数
- then中的两个函数
class MyPromise{
constructor(execute){
try {
execute(this.resolve,this.reject)
} catch (error) {
this.reject(error)
}
}
...
resolve = (value)=>{
...
while(this.successCallback.length) this.successCallback.shift()()
}
reject = (error)=>{
...
while(this.failCallback.length) this.failCallback.shift()()
}
then = (successCallback,failCallback)=>{
let p2 = new MyPromise((resolve,reject)=>{
if(this.status === FULFILLED){
setTimeout(()=>{
try {
let x = successCallback(this.successParams);
promiseResolve(p2,x,resolve,reject)
} catch (error) {
reject(error)
}
},0);
}
if(this.status === REJECTED){
setTimeout(()=>{
try {
let x = failCallback(this.failParams);
promiseResolve(p2,x,resolve,reject)
} catch (error) {
reject(error)
}
},0);
}
if(this.status === PENDING){
this.successCallback.push(()=>{
setTimeout(()=>{
try {
let x = successCallback(this.successParams);
promiseResolve(p2,x,resolve,reject)
} catch (error) {
reject(error)
}
},0);
});
this.failCallback.push(()=>{
setTimeout(()=>{
try {
let x = failCallback(this.failParams);
promiseResolve(p2,x,resolve,reject)
} catch (error) {
reject(error)
}
},0);
});
}
})
return p2;
}
}
注意:异步方法是在resolve/reject执行后,才执行下一个相应的then函数,
Promise还有一种调用方法.then中是空的
p.then().then().then(value=>console.log(value))
思路:在then中没有函数的时候,补齐函数(下面是源码)
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
class MyPromise{
constructor(execute){
try {
execute(this.resolve,this.reject)
} catch (error) {
this.reject(error)
}
}
status = PENDING;
successParams = undefined;
failParams = undefined;
successCallback = [];
failCallback = [];
resolve = (value)=>{
if(this.status !== PENDING) return;
this.status = FULFILLED;
this.successParams = value;
while(this.successCallback.length) this.successCallback.shift()()
}
reject = (error)=>{
if(this.status !== PENDING) return;
this.status = REJECTED;
this.failParams = error;
while(this.failCallback.length) this.failCallback.shift()()
}
then = (successCallback,failCallback)=>{
successCallback = successCallback ? successCallback : value => value;
failCallback = failCallback ? failCallback : value => value;
let p2 = new MyPromise((resolve,reject)=>{
if(this.status === FULFILLED){
setTimeout(()=>{
try {
let x = successCallback(this.successParams);
promiseResolve(p2,x,resolve,reject)
} catch (error) {
reject(error)
}
},0);
}
if(this.status === REJECTED){
setTimeout(()=>{
try {
let x = failCallback(this.failParams);
promiseResolve(p2,x,resolve,reject)
} catch (error) {
reject(error)
}
},0);
}
if(this.status === PENDING){
this.successCallback.push(()=>{
setTimeout(()=>{
try {
let x = successCallback(this.successParams);
promiseResolve(p2,x,resolve,reject)
} catch (error) {
reject(error)
}
},0);
});
this.failCallback.push(()=>{
setTimeout(()=>{
try {
let x = failCallback(this.failParams);
promiseResolve(p2,x,resolve,reject)
} catch (error) {
reject(error)
}
},0);
});
}
})
return p2;
}
}
function promiseResolve(p,x,resolve,reject){
if(p === x){
return reject(new TypeError('error'))
}
if(x instanceof MyPromise){
x.then(resolve,reject)
}else{
resolve(x)
}
}
如果有错误或者不严谨的地方,请务必给予指正,十分感谢。