参考资料

  1. MDN的一个使用实例,有讲顺序启动,并行启动之类的常用方法,其他的感觉讲的不如下面的资料清楚

  2. 自己写的这篇博客里说到的主要概念和理解都出自这篇材料,写的很好

  3. 这篇材料讲述了避免async/await hell的一个主要解决途径就是分离启动promise和resolve promise这两个过程

主要内容

  1. 描述了涉及async函数的主要概念,包括:

    • async函数的返回值Promise对象的创建工作过程
    • await操作符的作用
    • async函数中return和await的区别
  2. 描述了顺序启动和并行启动的方法

  3. 描述了是否使用await的区别

有待补充和学习的

  1. async的原理
  2. async函数的一些复杂的使用场景
  3. 其他异步执行方法,promise、yield的深入理解

对async函数使用的理解

  1. 局限在async函数内部,利用await
  2. 利用async函数的返回值promise对象

async函数是如何工作的

  1. The result of an async function is always a Promise p. That Promise is created when starting the execution of the async function.

  2. The body is executed. Execution may finish permanently via return or throw. Or it may finish temporarily via await, in which case execution will usually continue later on.

  3. The Promise p is returned.

When executing the body of the async function, return x resolves the Promise p with x, while throw err rejects p with err.

await的本质

waiting for a Promsie to be settled.

  1. if the Promise is fulfilled, the result of await is the fulfillment value(也就是说,此刻的结果是普通的值,而不是一个promsie对象, 比如下面的示例:)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    async function asyncFunc() {
    const result = await otherAsyncFunc();
    console.log(reuslt);
    }

    //上面这个函数完全等价于

    function asyncFunc() {
    return otherAsyncFunc()
    .then(reuslt => {
    console.log(result);
    });
    }
  2. If the promise is rejected, await throws the rejection value。这个同样有两种处理方式,一种是在async函数内部使用try…catch来解决,另一种是传到async函数外,使用catch来解决。

  3. await后面是个常数,则会以这种形式返回返回值:Promise.resolve(value)

async函数中的return

Resolving a Promise is a standard operation. return uses it to resolve the Promise p of an async function.

  1. Returning a non-Promise value fulfills p with that value

  2. Returning a Promise means that p now mirrors the state of that Promise

是否使用await

  1. 在返回语句中不使用await

    1
    2
    3
    4
    5
    6
    // 这个函数的返回值使用的是上面第二种情况
    // 效率高

    async function asyncFunc() {
    return anotherAsyncFunc();
    }
  2. 在返回语句中使用await

    1
    2
    3
    4
    5
    6
    // 下面这个函数的返回语句中会发生先解包(await解包),在包装(return 会再次包装成Promise.resolve的过程)
    // 效率低

    async function asyncFunc() {
    return await anotherAsyncFunc();
    }

async函数使用的几种场景(出自上述参考资料1)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
var resolveAfter2Seconds = function() {
console.log("starting slow promise");
return new Promise(resolve => {
setTimeout(function() {
resolve(20);
console.log("slow promise is done");
}, 2000);
});
};

var resolveAfter1Second = function() {
console.log("starting fast promise");
return new Promise(resolve => {
setTimeout(function() {
resolve(10);
console.log("fast promise is done");
}, 1000);
});
};

var sequentialStart = async function() {
console.log('==SEQUENTIAL START==');

// If the value of the expression following the await operator is not a Promise, it's converted to a resolved Promise.
const slow = await resolveAfter2Seconds();

const fast = await resolveAfter1Second();
console.log(slow);
console.log(fast);
}

var concurrentStart = async function() {
console.log('==CONCURRENT START with await==');
const slow = resolveAfter2Seconds(); // starts timer immediately
const fast = resolveAfter1Second();

console.log(await slow);
console.log(await fast); // waits for slow to finish, even though fast is already done!
}

var stillConcurrent = function() {
console.log('==CONCURRENT START with Promise.all==');
Promise.all([resolveAfter2Seconds(), resolveAfter1Second()]).then((messages) => {
console.log(messages[0]); // slow
console.log(messages[1]); // fast
});
}

var parallel = function() {
console.log('==PARALLEL with Promise.then==');
resolveAfter2Seconds().then((message)=>console.log(message));
resolveAfter1Second().then((message)=>console.log(message));
}