新建Promise实例时传入的函数的参数与回调函数的关系
部分内容引用自阮一峰-Promise
新建一个Promise实例:1
2
3
4
5
6
7
8
9const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。1
2
3
4
5promise.then(function(value) {
// success
}, function(error) {
// failure
});
在创建Promise实例时,传入的函数有两个参数resolve和reject都是函数,这两个参数由JavaScript引擎提供,resolve函数用来将Promise实例的状态从Pending变为resolved,并通过resolve(value)的形式从Promise中返回value值。
在Promise实例状态从pending变为resolved后,then()方法中指定的第一个回调函数接受上述返回值value将其作为参数并执行。
容易产生的误区:
1.不要把回调函数当做创建
Primise时传入的函数的参数resolve和reject,即使Promise没有回调函数,在创建时依然由Javascript引擎提供了resolve和reject,这两个参数只负责改变Promise实例的状态,并从Promise实例中返回值,then()中的回调函数只是接受了这个返回值而已。
2.
then()中的回调函数指的是Promise实例状态改变时的回调函数,只要在Promise创建时执行了resolve或者reject,那么就会去调用回调函数,不论Promise实例是否有返回值。也就是说,resolve()和resolve(value)都会触发Promise状态改变,都会调用then中的第一个回调函数。
Promise链中then是如何传递参数的
这部分的详细内容可以参考Promise#then
function doubleUp(value) {
return value * 2;
}
function increment(value) {
return value + 1;
}
function output(value) {
console.log(value);// => (1 + 1) * 2
}
var promise = Promise.resolve(1);
promise
.then(increment)
.then(doubleUp)
.then(output)
.catch(function(error){
// promise chain中出现异常的时候会被调用
console.error(error);
});
在第一个then的回调函数increment中,返回了一个值 1 * 2,但是这个值是怎么传给第二个then的回调函数doubleUp里面做参数呢?这个问题我很长一段时间里都没搞明白,只知道怎么用不知道怎么传的。
实际上在increment函数里 return 2的时候, Promise对返回值进行了封装,相当于执行了
return new Promise.resolve(2)
//如果increment函数没有返回值,则只返回一个Promise实例,相当于执行了
return new Promise.resolve()
//如果发生错误的话,也可能返回
return new Promise.reject(new Error('发生了错误'))
所以每一个then函数都会返回一个新的resolved或reject状态的Promise实例,并将返回值传入下一个then的回调函数作为参数
await 与 Promise
1.在async函数内部,我们可以认为 当 await 某个 Promise 时,函数暂停执行,直至该 Promise 产生结果,并且暂停并不会阻塞主线程,也就是会继续执行 async 函数外的逻辑。
利用await的这种特性可以做延时,如下:1
2
3
4
5
6
7
8
9
10
11async function test() {
let xx = 1234;
await new Promise((resolve) => {
setTimeout(() => {
resolve();
}, 2000);
});
// 然后再执行需要延时后再处理的逻辑
xx = 5678;
}
上面代码中xx = 5678是在2秒延时后再执行的。
await中的promise如果没有执行resolve或者reject,则await后面的逻辑永远不会执行到。如下:
1
2
3
4
5
6
7
8
9
10
11 async function test() {
let xx = 1234;
await new Promise((resolve) => {
setTimeout(() => {
// resolve();
}, 2000);
});
// 下面的逻辑永远执行不到
xx = 5678;
}
2.当一个 async 函数被调用,它返回一个 Promise。当 async 函数返回一个值,它不是一个 Promise,Promise 将会被自动创建,然后它使用函数的返回值来决定状态。当 async 抛出一个异常,Promise 使用抛出的值进入已失败状态。