对Promise的理解

新建Promise实例时传入的函数的参数与回调函数的关系

部分内容引用自阮一峰-Promise

新建一个Promise实例:

1
2
3
4
5
6
7
8
9
const promise = new Promise(function(resolve, reject) {
// ... some code

if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});

Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。

1
2
3
4
5
promise.then(function(value) {
// success
}, function(error) {
// failure
});

在创建Promise实例时,传入的函数有两个参数resolvereject都是函数,这两个参数由JavaScript引擎提供,resolve函数用来将Promise实例的状态从Pending变为resolved,并通过resolve(value)的形式从Promise中返回value值。

在Promise实例状态从pending变为resolved后,then()方法中指定的第一个回调函数接受上述返回值value将其作为参数并执行。

容易产生的误区:

1.不要把回调函数当做创建Primise时传入的函数的参数resolvereject,即使Promise没有回调函数,在创建时依然由Javascript引擎提供了resolvereject,这两个参数只负责改变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

阮一峰 async函数介绍

理解透彻这个 async await、Promise、setTimeout执行顺序

1.在async函数内部,我们可以认为 当 await 某个 Promise 时,函数暂停执行,直至该 Promise 产生结果,并且暂停并不会阻塞主线程,也就是会继续执行 async 函数外的逻辑。

利用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;
}

上面代码中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 函数返回一个值,它不是一个 PromisePromise 将会被自动创建,然后它使用函数的返回值来决定状态。当 async 抛出一个异常,Promise 使用抛出的值进入已失败状态。