理解JavaScript中async/await

原文:Understanding Async/Await in JavaScript

async/await可以用同步的方式写异步代码,没有回调函数或Promise链,可以在for循环和if语句中使用。

async/await可以用同步的方式写异步代码,在异步函数中,可以用if语句、for循环和try/catch。

async

async关键字表示一个函数是异步函数。以下示例中,test()是异步函数。

1
2
3
async function test() {
return 42;
}

也可以定义一个异步的箭头函数:

1
const test = async () => 42;

await

async函数的特殊之处在于,可以在函数中使用await关键字,如果await一个Promise,会暂停执行该函数,直到Promise变为fulfilled或rejectedawait还会解开Promise的包装,取得Promise变为fulfilled的值。

1
2
3
4
5
6
7
async function test() {
// `await`解包了Promise的值
const val = await Promise.resolve(42);
val; // 42
}

test();

在以上示例中,Promise.resolve()函数代表这个Promise会立刻变为fulfilled。在以下示例中,await暂停了test()函数100毫秒:

1
2
3
4
5
6
async function test() {
const start = Date.now();
await new Promise(resolve => setTimeout(resolve, 100));
const elapsed = Date.now() - start;
elapsed; // about 100
}

await是JavaScript的一个普通的关键字,可以在if语句、for循环和try/catch中使用。

1
2
3
4
5
6
7
8
9
10
11
async function asyncEvenNumbers() {
const nums = [];
for (let i = 1; i <= 10; ++i) {
if (i % 2 === 0) {
const v = await Promise.resolve(i);
nums.push(v);
}
}

nums; // [2, 4, 6, 8, 10]
}

返回值

async函数的另一个特殊之处在于,它总是返回一个Promise。即使在async函数中返回的是一个原始类型的值,JavaScript会将它包装为Promise。

1
2
3
4
5
6
7
8
9
async function test() {
return 42;
}

const p = test();
p instanceof Promise; // true
p.then(v => {
v; // 42
});

也就是说,可以对async函数使用await

1
2
3
4
5
6
7
8
async function test() {
return 42;
}

async function main() {
const val = await test();
val; // 42
}

错误处理

async/await的错误处理是一个复杂的话题。但是,大体上有两种错误处理的模式。

await一个Promise时,Promise变为rejected,await会抛出一个错误,可以用try/catch捕获:

1
2
3
4
5
6
7
async function test() {
try {
await Promise.reject(new Error('Oops'));
} catch (err) {
err.message; // Oops
}
}

也可以用Promise#catch()函数解包Promise的错误:

1
2
3
4
5
6
7
async function test() {
const promise = Promise.reject(new Error('Oops'));

// Unwrap the promise's error
const err = await promise.catch(err => err);
err.message; // 'Oops'
}

async/await是JavaScript中并发的未来趋势。“Mastering Async/Await”教你如何在几个小时内,用async/await构建前后端APP,来看看吧!