好家伙,本篇为《JS高级程序设计》第十章“期约与异步函数”学习笔记

ES8 的 async/await 旨在解决利用异步结构组织代码的问题。

为为此增加了两个新关键字:async 和 await。

1.async关键字

1.1.使用说明

async 关键字用于声明异步函数。

函数声明、函数表达式、箭头函数和方法都可以使用

使用 async 关键字可以让函数具有异步特征,但总体上其代码仍然是同步求值的。

而在参数或闭包方面,异步函数仍然具有普通 JavaScript 函数的正常行为。

async function foo() {}
let bar = async function() {}; 
let baz = async () => {}; 
class Qux { 
 async qux() {} 
} 

第126篇: 异步函数(async和await)

1.2.返回值

异步函数如果使用 return 关键字返回了值(如果没有 return 则会返回 undefined),这个值会被 Promise.resolve()包装成一个期约对象。

异步函数始终返回期约对象。

async function foo() {
    return 3; 
   } 
console.log(foo());

第126篇: 异步函数(async和await)

也可以直接返回一个契约

async function bar() {
    console.log("I am bar");
    return Promise.resolve(3);
}
console.log("--------------");
console.log(bar());
console.log(1);

第126篇: 异步函数(async和await)

1.3.在异步函数中抛出错误会返回拒绝的期约

async function foo() {
 console.log(1); 
 throw 3; 
} 
// 给返回的期约添加一个拒绝处理程序
foo().catch(console.log);
console.log(2); 

第126篇: 异步函数(async和await)

1.4.但是,拒绝期约的错误不会被异步函数捕获

async function foo() {
 console.log(1); 
 Promise.reject(3); 
} 
// Attach a rejected handler to the returned promise 
foo().catch(console.log); 
console.log(2); 

第126篇: 异步函数(async和await)

2.await关键字

这里我们拆分一下 a-wait

也就是asynchronous-wait 异步-暂停

异步函数主要针对不会马上完成的任务,所以自然需要一种暂停和恢复执行的能力。

使用 await 关键字可以暂停异步函数代码的执行,等待期约解决。

(是暂停异步)

基本使用

async function foo() {
    let p = new Promise((resolve, reject) => setTimeout(resolve, 1000, 3));
    console.log(await p);
}
foo();
// 3 (一秒钟后出现) 

第126篇: 异步函数(async和await)

(然而这好像看不出什么)

要完全理解 await 关键字,必须知道它并非只是等待一个值可用那么简单。

JavaScript 运行时在碰 到 await 关键字时,会记录在哪里暂停执行。

等到 await 右边的值可用了,JavaScript 运行时会向消息 队列中推送一个任务,这个任务会恢复异步函数的执行。

async function foo(){
    console.log(1);
    console.log( await 4);
}
foo();
console.log(2);
console.log(3);

第126篇: 异步函数(async和await)

这里我们按上面的话尝试翻译一下发生了什么事

(1)调用异步函数foo()

(2)输出1

(3)准备打印,一看诶有个await,先暂停,为立即可用的值4向消息队列中添加一个任务,

( 怎么说呢,我反复看了很多遍.这里的意思大概是把一个要求值或者说要返回结果的式子推进消息队列,

但这里就只有一个4,求个毛线,直接就是4,就是把这个4推进消息队列. ),后让出线程

(4)执行同步函数输出 2

(5)输出3

(6)"4"求出来了,就是4

(7)await右边出值了,向消息队列中添加一个"恢复foo()执行"的任务

(8)从消息队列中取出"恢复foo()执行"的任务,恢复foo()异步函数的执行

(9)输出4

大概就是这么个过程

3.课后习题

1.请给出下列代码的输出结果,并配合"消息队列"写出相关解释

async function foo() {
    console.log(2);
    console.log(await Promise.resolve(8));
    console.log(9);
}
async function bar() {
    console.log(4);
    console.log(await 6);
    console.log(7);
}
console.log(1);
foo();
console.log(3);
bar();
console.log(5);

尝试做一下吧,结果一定出乎你的意料

(明天再出一章写解释)

发表回复