async被称为终极的异步解决方案,避免了回调地狱,用同步的写法处理异步操作
async和Generator
async
是Generator
的语法糖,两者写法非常相似;
Generator
代码实例:
function* gen(){ //声明一个Generator函数
yield '1'
yield '2'
yield '3'
}
let g = gen() //调用该函数,返回指向内部状态的指针对象
console.log(g.next().value) // g.next返回一个对象 { value: yield表达式后的值, done: false }
Generator
必须手动调用next
方法才会开始遍历,async
则会自动执行,输出最后结果,且async
返回值是一个Promise对象,可以直接通过then指定下一个操作;
举个栗子:
用Promise封装一个文件读取的函数
const fs = require('fs')
const readFile = function(fileName){
return new Promise((resolve, reject) => {
fs.readFile(fileName, (error, data) => {
if(error) return reject(error)
resolve(data)
})
})
}
定义一个async函数,读取异步读取两个文件
async function gen(){
let f1 = await readFile('text/1.txt') //await 后可以跟Promise 对象和原始类型的值
const f2 = await readFile('text/2.txt')
console.log('f1 content ' + f1)
console.log(`f2 content ${f2}`)
return 'returnValue'
}
直接执行,获取返回值
gen().then((v) => {
console.log(v) // 打印字符串 returnValue
})
await
命令后面是一个Promise
对象,如果不是,会被转成一个立即resolve
的 Promise
对象。
当存在多个
await
时,只要有一个await
后的Promise
变成reject
,则后面的await
将不再执行。可以使用catch
进行错误的捕获;或者把await
命令放在try...catch
代码块中。
async function f() {
await Promise.reject('出错了')
.catch(e => console.log(e));
return await Promise.resolve('hello world');
}
f()
.then(v => console.log(v))
// 出错了
// hello world
当多个await之间不存在依赖关系时,要让他们同时触发,
let foo = await getFoo();
let bar = await getBar(); //不相互依赖,默认会继发执行
通过处理,让他们同时触发
// 写法一
//Promise.all用于将多个 Promise 实例包装成一个新的 Promise 实例
let [foo, bar] = await Promise.all([getFoo(), getBar()]);
// 写法二
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;
参考文献
[1].阮一峰老师文章