Javascript中的async函数详解
前言:async 是“异步”的简写,async 用于申明一个 function 是异步的,而 await 用于等待一个异步方法执行完成,await 只能出现在 async 函数中。
Generator 函数:
var fs = require('fs'); var readFile = function (fileName){ return new Promise(function (resolve, reject){ fs.readFile(fileName, function(error, data){ if (error) reject(error); resolve(data); }); }); };
var gen = function* (){ var f1 = yield readFile('/etc/fstab'); var f2 = yield readFile('/etc/shells'); console.log(f1.toString()); console.log(f2.toString()); }
async 函数
var asyncReadFile = async function (){ var f1 = await readFile('/etc/fstab'); var f2 = await readFile('/etc/shells'); console.log(f1.toString()); console.log(f2.toString()); };
显而易见,async函数中async就是将 Generator 函数的星号(*)替换成 async,await等价于yield。
async 函数是非常新的语法功能,属于 ES7。目前,它仍处于提案阶段,但是转码器 Babel 和 regenerator 都已经支持,转码后就能使用。
但async 函数对 Generator 函数做了改进:
1、内置执行器:Generator函数的执行必须靠执行器,所以才有了 co 函数库,而 async 函数自带执行器.也就是说,async 函数的执行,与普通函数一模一样。
var result = asyncReadFile();
2、更好的语义:async 和 await,比起星号和 yield,语义更清楚了。async 表示函数里有异步操作,await 表示紧跟在后面的表达式需要等待结果。
3、更广的适用性:co 函数库约定,yield 命令后面只能是 Thunk 函数或 Promise 对象,而 async 函数的 await 命令后面,可以跟 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)。
async 的作用
async 函数负责返回一个 Promise 对象,如果在async函数中 return 一个直接量,async 会把这个直接量通过Promise.resolve() 封装成 Promise 对象;如果 async 函数没有返回值,它会返回 Promise.resolve(undefined)。
await 在等待什么
如果await等到的不是一个promise对象,那跟着的表达式的运算结果就是它等到的东西;
如果是一个promise对象,await会阻塞后面的代码,等promise对象resolve,得到resolve的值作为await表达式的运算结果。
虽然await阻塞了,但await在async中,async不会阻塞,它内部所有的阻塞都被封装在一个promise对象中异步执行。