async和await
async 函数是什么?一句话,它就是 Generator 函数的语法糖,使得异步操作变得更加方便。
基本使用
const fs = require("fs"); const readFile = function(url){ return new Promise((resolve,reject)=>{ fs.readFile(url,(err,content)=>{ if(err){ reject(err) return; } resolve(content.toString()) }) } ) } async function files(){ const data1 = await readFile("./text.txt"); const data2 = await readFile("./text2.txt"); const data3 = await readFile("./text3.txt"); console.log(data1); console.log(data2); console.log(data3); } files() console.log("我执行了");
此时输出是异步执行的
发现上面files函数中await语句后面的readFile没有使用.then,也能返回结果,此时和我们加then的效果是一样的
const fs = require("fs"); const readFile = function(url){ return new Promise((resolve,reject)=>{ fs.readFile(url,(err,content)=>{ if(err){ reject(err) return; } resolve(content.toString()) }) } ) } async function files(){ const data1 = await readFile("./text.txt").then((data)=>{ console.log(data); return readFile("./text2.txt") }).then((data)=>{ console.log(data); return readFile("./text3.txt") }).then((data)=>{ console.log(data) }).catch((err)=>{ console.log(err) }) } files() console.log("我执行了");
任何一个函数都能加async这个关键词,表示这个函数内部要书写异步代码
async表示定义当前的函数为一个异步函数,await只能用在async定义的函数内有效,表示等待异步读取的结果,如果在普通函数中会报错
此时函数内部是如何运行的?
const fs = require("fs"); const readFile = function(url){ return new Promise((resolve,reject)=>{ fs.readFile(url,(err,content)=>{ if(err){ reject(err) return; } resolve(content.toString()) }) } ) } async function files(){ const data1 = await readFile("./text.txt"); console.log("我在data1中"); console.log(data1); const data2 = await readFile("./text2.txt"); console.log("我在data2中"); console.log(data2); const data3 = await readFile("./text3.txt"); console.log("我在data3中"); console.log(data3); } files() console.log("我执行了");
此时会发现先输出我执行了,表示当前整个函数是异步的,然后函数体内部是按照同步代码执行的,也就是await将异步语句变为了同步语句在执行
async函数
async函数返回一个Promise对象
此时可以通过then来调用获取值
函数内部抛出错误,会导致返回的Promise对象变为reject状态。抛出的错误对象会被catch方法回调函数接收到。
await命令
await命令后面是一个Promise对象。如果不是,会被转成一个立即resolve的Promise对象。也就是说,如果不是promise对象,此时函数内部返回的时候会自动包一个promise的壳子
await命令后面的Promise对象如果变为reject状态,则reject的参数会被catch方法的回调函数接收到。
async函数的错误机制问题
可以通过try-catch来进行错误机制的处理
async函数的多种使用形式
// 函数声明 async function fun() {} // 函数表达式 const fun = async function () {}; // 对象的方法 let obj = { async fun() {} }; obj.fun().then(...) // Class 的方法 class Storage { constructor() { this.cachePromise = caches.open('avatars'); } async getAvatar(name) { const cache = await this.cachePromise; return cache.match(`/avatars/${name}.jpg`); } } const storage = new Storage(); storage.getAvatar('jake').then(...); // 箭头函数 const fun = async () => {};
for await...of遍历异步
for await...of
语句创建一个循环,该循环遍历异步可迭代对象以及同步可迭代对象,包括: 内置的 String
, Array
,类似数组对象 (例如 arguments
或 NodeList
),TypedArray
, Map
, Set
和用户定义的异步/同步迭代器。它使用对象的每个不同属性的值调用要执行的语句来调用自定义迭代钩子。
类似于 await
运算符一样,该语句只能在一个async function 内部使用。
语法:
for await (variable of iterable) { //statement }
variable
在每次迭代中,将不同属性的值分配给变量。变量有可能以const
, let
, 或者 var
来声明。
iterable
被迭代枚举其属性的对象。与 for...of 相比,这里的对象可以返回 Promise
,如果是这样,那么 variable
将是 Promise
所包含的值,否则是值本身。
迭代异步可迭代对象
var asyncIterable = { [Symbol.asyncIterator]() { return { i: 0, next() { if (this.i < 3) { return Promise.resolve({ value: this.i++, done: false }); } return Promise.resolve({ done: true }); } }; } }; (async function() { for await (num of asyncIterable) { console.log(num); } })();
迭代异步生成器
async function* asyncGenerator() { var i = 0; while (i < 3) { yield i++; } } (async function() { for await (num of asyncGenerator()) { console.log(num); } })();