async 函数是什么?一句话,它就是 Generator 函数的语法糖。 —es6入门
Generator的用法
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
hw.next() // { value: 'hello', done: false }
hw.next() //{ value: 'world', done: false }
hw.next() //{ value: 'ending', done: true }
Generator和async的比较
const gen = function* () {
const f1 = yield readFile('/etc/fstab');
const f2 = yield readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};
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,yield变成await,
*Generator 函数的执行必须靠执行器,所以才有了co
模块,而async
函数自带执行器
所以在使用的时候async函数直接调用即可,而generator需要调用并使用next
var test = gen()
test.next() //输出第一个yield
async用法
async的用法比较简单,函数声明成async函数,并在函数中的异步函数前加await,当执行到异步函数时,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);
async在循环中的使用
async可以使用在循环中,但是不会改变循环的执行时间,只会改变循环中函数的执行。循环依然会依次快速的执行完,不会等一个循环执行结果在执行第二个循环。
例如:
var a=[3000,1000,2000]
var timePrint = (time)=>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(time)
resolve(time)
},time)
})
}
a.forEach(async time=>{
await timePrint(time)
})
上述代码,for循环中有三个异步操作,第一个3秒返回结果,第二个1秒返回结果,最后一个2秒返回结果,
最后输出的结果是1000、2000、3000. 输出的结果完全是按照时间长短顺序来的。
async并不会影响for循环的执行顺序,也不会影响for循环的执行时间。
for循环执行时,就立即创建了三个异步操作,内部函数的执行是相对独立的异步操作,函数内部的执行顺序是可以受await控制的,如下:
如何依次执行Promise
如果希望promise依次执行如何操作呢,for循环不行的话,我们可以考虑使用递归循环,在上一个函数结束之后在调用下一个循环,使用await控制运行的顺序
var a=[3000,1000,2000]
var timePrint = (time)=>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(time)
resolve(time)
},time)
})
}
var index = 0
var test = async function(){
await timePrint(a[index])
index++
if(index<a.length){
test()
}
}
test()