Open bibi7 opened 5 years ago
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);
async有两个特点:
pending
状态的promiseasync 函数有多种使用形式:
// 函数声明
async function foo() {}
// 函数表达式
const foo = async function () {};
// 对象的方法
let obj = { async foo() {} };
obj.foo().then(...)
// Class 的方法
class Storage {
constructor() {
this.cachePromise = caches.open('avatars');
}
async getAvatar(name) {
const cache = await this.cachePromise;
return cache.match(`/avatars/${name}.jpg`);
}
}
const storage = new Storage();
storage.getAvatar('jake').then(…);
// 箭头函数
const foo = async () => {};
简化的sleep实现:
function sleep(interval) {
return new Promise(resolve => {
setTimeout(resolve, interval);
})
}
// 用法
async function one2FiveInAsync() {
for(let i = 1; i <= 5; i++) {
console.log(i);
await sleep(1000);
}
}
one2FiveInAsync();
var multi = num => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(num * num)
}, 1000)
})
}
async function test () {
var nums = [1,2,3]
nums.forEach(async x => {
var res = await multi(x)
console.log(res)
})
}
test()
期望的打印是每隔一秒打印一个数字,但是现在获得的结果是等了一秒一起输出结果。
在本例中 forEach 的回调函数是一个异步函数,异步函数中包含一个 await 等待 Promise 返回结果,我们期望数组元素串行执行这个异步操作,实际上是并行执行。
forEach 的 polyfill 参考:MDN-Array.prototype.forEach(),简单点理解:
Array.prototype.forEach = function (callback) {
// this represents our array
for (let index = 0; index < this.length; index++) {
// We call the callback for each entry
callback(this[index], index, this)
}
}
//相当于是for循环并行执行了异步函数
说白了就是,虽然callBack是一个具有await的异步调用,但是这一堆callback本身是同步执行
既然这样,要改造其实就有点思路了,比如可以直接让forEach确保每一个回调执行后再执行下一个:
Array.prototype.forEachAsync = async function (callback) {
for (let index = 0; index < this.length; index++) {
await callback(this[index], index, this)
}
}
可以采用内部基于迭代器的for of
形式代替:
async function test () {
var nums = [1,2,3]
for (let num of nums) {
var res = await multi(num)
console.log(res)
}
}
api版本,新增了Promise.all
的方式(这个我倒是没试过
Array.prototype.forEachAsync = async function (fn) {
for (let t of this) { await fn(t) }
}
Array.prototype.forEachAsyncParallel = async function (fn) {
await Promise.all(this.map(fn));
}
async function async1(){
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2(){
console.log('async2')
}
console.log('script start')
setTimeout(function(){
console.log('setTimeout')
},0)
async1();
new Promise(function(resolve){
console.log('promise1')
resolve();
}).then(function(){
console.log('promise2')
})
console.log('script end')
关于这道题,promise2
和async1 end
在不同的浏览器环境,不同的v8版本之间都会有先后不同的表现。
具体原因可见:
async/await 在chrome 环境和 node 环境的 执行结果不一致,求解?
related to #15
其实除了异步两个字以外也没啥关联。。。 大部分都是api相关基础知识,摘自阮一峰