async
要理解 async 先要掌握 Promise 的概念,了解 Promise 请戳我!
async 函数是什么?一句话,它就是 Genervator 函数的语法糖。
一个 Genervator 函数,依次读取两个文件。
const fs = require('fs');
const readFile = function(fileName) {
return new Promise((resolve, reject) => {
fs.readFile(fileName, (error, data) => {
if (error) return reject(error);
reslove(data);
})
})
}
const gen = function* () {
const f1 = yield readFile('/etc/fstab');
const f2 = yield readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
}
改写成 async 函数。
const asyncReadFile = async function() {
// 一旦遇到 await 就先返回,等到异步操作完成再继续执行函数体后面的语句
const f1 = await readFile('/etc/fstab');
const f2 = await readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
}
async 函数返回的是一个 Promise 对象。进一步说,async 函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而内部的 await
命令就是内部 then
的语法糖。
// async 返回一个 Promise 对象
async function f() {
return 'hello world';
}
// .then 调用 Promise 对象
f().then(v => console.log(v));
// "hello world"
async 内部抛出的异常会导致 Promise 对象变成 reject
的状态,能够被 catch
捕获。
async function f() {
throw new Error('出错了');
}
f().then(v => console.log(v))
.catch(e => console.log(e));
// Error: 出错了
await
正常情况下,await 命令后面是一个 Promise 对象。如果不是,会被转换成一个立即 resolve
的 Promise 对象。
async funciton () {
return await 123;
}
f().then(v => console.log(v));
// 123
只要 await 语句后面的 Promise 变成 reject
,那么整个 async 函数都会中断执行。
async function f() {
await Promise.reject('出错了');
await Promise.reslove('hello world'); // 不会执行
}
如果需要避免这个问题,可以是用 try...catch
。
async function f() {
try {
await Promise.reject('出错了');
} catch(e) {
}
return await Promise.resolve('hello world');
}
f()
.then(v => console.log(v))
// hello world
案例: 按顺序完成异步操作
实际的开发中,经常遇到一组异步操作需要按顺序完成。比如,以此远程读取一组 URL,然后按照读取顺序依次输出。
async function loginOrder(urls) {
// 并发读取远程URL
const textPromises = urls.map(async url => {
const response = await fetch(url);
return response.text();
})
// 按次序输出
for (const textPromise of textPromises) {
console.log(await textPromise);
}
}
网友评论