一、async和await是什么 ES2017 标准引入了 async 函数,使得异步操作变得更加方便,async其实本质是Generator函数的语法糖 async表示函数里有异步操作 await表示在后面的表达式需要等待结果
一、async和await是什么
ES2017 标准引入了 async 函数,使得异步操作变得更加方便,async其实本质是Generator函数的语法糖
- async表示函数里有异步操作
- await表示在后面的表达式需要等待结果
- async函数返回的是一个Promise对象,可以使用then方法添加回调函数,一旦遇到await就会先返回。
二、node异步编程演进的四个阶段
我们来回顾一下异步编程的写法的演进过程
第一阶段 通过回调函数
fs.readFile('/etc/passwd', 'utf-8', function (err, data) { if (err) throw err; console.log(data); })
这样的方式会造成嵌套过多,在调用过多的时候,就变成了下面这样的写法,传说中的callback hell
fs.readFile(fileA, 'utf-8', function (err, data) { fs.readFile(fileB, 'utf-8', function (err, data) { fs.readFile(fileC, 'utf-8', function (err, data) { // ... }); }); });
2. 第二阶段 通过Promise
Promise 对象允许将回调函数的嵌套,改成链式调用。
采用 Promise,连续读取多个文件,写法如下。
const readFile = function (fileName) { return new Promise(function (resolve, reject) { fs.readFile(fileName, function(error, data) { if (error) return reject(error); resolve(data); }); }); };
当操作很多的时候就变成了下面这样的写法
var readFile = require('fs-readfile-promise'); readFile(fileA) .then(function (data) { console.log(data.toString()); }) .then(function () { return readFile(fileB); }) .then(function (data) { console.log(data.toString()); }) .catch(function (err) { console.log(err); });
这样虽然比callback好了,但是有一个问题是代码冗余,不管什么操作,看上去都是一堆then
3.第三个阶段 通过Generator函数
function* asyncJob() { // ...其他代码 var f = yield readFile(fileA); // ...其他代码 }
函数asyncJob是一个协程,协程遇到yield命令就暂停,等到执行权返回,再从暂停的地方继续往后执行,这样的写法非常像同步操作。
要想使用yield方法,得不停地执行next()切换到下一个yeild,调用变成了下面这样
var fs = require('fs'); var readFile = function (fileName){ return new Promise(function (resolve, reject){ fs.readFile(fileName, function(error, data){ if (error) return 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()); };
第4个阶段 通过async和await
async 函数本质就是 Generator 函数的语法糖
最后演变成了下面这样的写法
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和await,比起*和yield,语义更清楚了。 async表示函数里有异步操作,await表示在后面的表达式需要等待结果 async函数的返回值是Promise对象 await后面,可以是Promise对象和原始类型的值(数值、字符串和布尔值,会自动转换成resolved的Promise对象)