async函数原理及使用方法
async 函数是什么?一句话,它就是 Generator 函数的语法糖,async 函数的实现原理,就是将 Generator 函数和自动执行器,包装在一个函数里。
1,Generator 函数
const fs = require('fs'); const readFile = function (fileName) { return new Promise(function (resolve, reject) { fs.readFile(fileName, function(error, data) { if (error) return reject(error); resolve(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 () { const f1 = await readFile('/etc/fstab'); const f2 = await readFile('/etc/shells'); console.log(f1.toString()); console.log(f2.toString()); };
一比较就会发现,async
函数就是将 Generator 函数的星号(*
)替换成async
,将yield
替换成await
,仅此而已。
async只不过将Generator进行了一些改进;
2,async具体使用和优点
async
函数返回一个 Promise 对象,可以使用then
方法添加回调函数。当函数执行的时候,一旦遇到await
就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
function timeout(ms) { return new Promise((resolve) => { setTimeout(resolve, ms); }); } async function asyncPrint(value, ms) { await timeout(ms); console.log(value); } asyncPrint('hello world', 50);
上面代码指定 50 毫秒以后,输出hello world
。
async异步函数变体:
异步函数声明: async function foo() {} 异步函数表达式: const foo = async function () {}; 异步函数定义:let obj = { async foo() {} } 异步箭头函数: const foo = async () => {};
理解:
-
async 表示这是一个 async 函数,而 await 只能在这个函数里面使用。
-
await 表示在这里等待 await 后面的操作执行完毕,再执行下一句代码。
-
await 后面紧跟着的最好是一个耗时的操作或者是一个异步操作(当然非耗时的操作也可以的,但是就失去意义了)。
3,错误处理
如果await
后面的异步操作出错,那么等同于async
函数返回的 Promise 对象被reject
。
async function f() { await new Promise(function (resolve, reject) { throw new Error('出错了'); }); } f() .then(v => console.log(v)) .catch(e => console.log(e)) // Error:出错了
防止出错的方法,也是将其放在try...catch
代码块之中。
async function main() { try { const val1 = await firstStep(); const val2 = await secondStep(val1); const val3 = await thirdStep(val1, val2); console.log('Final: ', val3); } catch (err) { console.error(err); } }
说白了async也是一个Promis对象,我们可以在async后面加上then或者catch这个东西来防止出错。