Promise定义
在promise以前,js用回调函数来处理异步请求,当上一次请求和下一次请求存在依赖关系的时候,就会出现回调地狱,类似这样嵌套回调
$.post('/getUser', function(data) {
$.post('/getInfo', userId: data.id, function(){
...
})
})
为了更好的异步流程控制,es6出现了promise,promsie对象,也是可以用来实现异步的,简单的语法如下
new Promise(
/* executor */
function(resolve, reject){...}
);
Promise状态
promise有以下三种状态,只要有一种状态被填充,一个promise就执行完毕,可以通过then
或者catch
来捕捉填充的状态,状态不可逆
- pending: 初始状态, 初始状态,未完成或拒绝。
- fulfilled: 意味着操作成功完成。
- rejected: 意味着操作失败。
Promise方法
这个方法返回一个新的promise对象,该promise对象在iterable里所有的promise对象都成功的时候才会触发成功,一旦有任何一个iterable里面的promise对象失败则立即触发该promise对象的失败。这个新的promise对象在触发成功状态以后,会把一个包含iterable里所有promise返回值的数组作为成功回调的返回值,顺序跟iterable的顺序保持一致;如果这个新的promise对象触发了失败状态,它会把iterable里第一个触发失败的promise对象的错误信息作为它的失败错误信息。Promise.all方法常被用于处理多个promise对象的状态集合。
const pro1 = new Promise((resolve, reject) => {
resolve('pro1结果')
});
const pro2 = new Promise((resolve, reject) => {
resolve('pro2结果');
})
Promise.all([pro1, pro2]).then((res1) => {
console.log(res1); // ['pro1结果', 'pro2结果']
})
当iterable参数里的任意一个子promise被成功或失败后,父promise马上也会用子promise的成功返回值或失败详情作为参数调用父promise绑定的相应句柄,并返回该promise对象。
const pro1 = new Promise((resolve, reject) => {
setTimeout(resolve(100), 100)
});
const pro2 = new Promise((resolve, reject) => {
setTimeout(resolve(200), 500);
})
Promise.race([pro1, pro2]).then((res) => {
console.log(res); // pro1先完成,结果是100
})
调用Promise的rejected句柄,并返回这个Promise对象。
用成功值value完成一个Promise对象。如果该value为可继续的(thenable,即带有then方法),返回的Promise对象会“跟随”这个value,采用这个value的最终状态;否则的话返回值会用这个value满足(fullfil)返回的Promise对象。
Promise错误捕捉
当有多个promise链式调用的时候,其中一个填充了reject状态,后续的将不会继续执行,例如
function dealOne () {
return new Promise((resolve, reject) => {
setTimeout(resolve(200), 500);
});
}
function dealTwo (a) {
return new Promise((resolve, reject) => {
reject('error')
})
}
function dealThree () {
return new Promise((resolve, reject) => {
resolve('3')
})
}
dealOne().then(dealTwo).then(dealThree).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
})
在dealTwo函数中,操作失败了,catch就会捕捉到错误,dealThree不会继续执行
当promise发生错误(reject)时,有两种方法,
1. 通过链式调用catch可以捕捉reject的结果
2. 通过then的第二个回调函数捕捉
dealTwo().then((res) => {}, (err) => { console.log('then ' + err) }).catch( err => console.log('catch' + err) )
在这里由于then的第二个回调捕捉了错误,所以先输出的结果为‘then error’,后面的catch就不执行了
Promise问题
function doSomething() {
return new Promise((resolve, reject) => {
resolve('doSomething');
})
}
function doSomethingElse() {
return new Promise((resolve, reject) => {
resolve('doSomethingElse');
})
}
doSomething().then(function () {
return doSomethingElse();
}).then(res => {
console.log(res);
});
doSomething().then(function (res) {
console.log('receive: ' + res)
doSomethingElse();
}).then(res => {
console.log(res); // undefined
});
doSomething().then(doSomethingElse()).then(res => {
console.log(res);
});
doSomething().then(doSomethingElse).then(res => {
console.log(res);
});
这四个东西有什么区别呢?
第一个很好理解:结果是doSomethingElse
第二个,由于第一个then有一个回调函数接收了结果,但是没返回新的promise,所以结果是undefined,其实相当于
doSomething().then(function (res) {
console.log('receive: ' + res)
doSomethingElse();
}).then(res => {
console.log(res); // undefined
});
第三个,由于then后执行了一个普通函数,所以doSomething()的值会穿透到下一个then接收,类似下面的例子
doSomething().then(null).then().then(res => {
console.log(res); // doSomething
})
第四个,其实跟第一个一样,只是简单的写法,所以结果是doSomethingElse
参考资料: https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html