异步迭代器,generator,for await of
这些东西好像看起来抽象,其实不然。现在假设有这么一个业务场景,有n个文件,需要先删除第1个、再删除第2个、第3个...第n个,你会怎么写?
已知如下文件列表,删除函数,该函数是异步的
const files = Array(100).fill(0).map((t, i) => ('file' + i));
// 删除文件函数
function deleteFile(index) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(`已删除第${index+1}个文件`);
resolve();
}, 50);
})
}
写法一:
一开始我是这么写的,就是一个递归写法,判断删完没有,没有就继续删
let deletedCount = 0;
async function handler(index) {
await deleteFile(index);
if (deletedCount < files.length - 1) {
deletedCount++;
await handler(index + 1);
}
}
handler(0);
后面想到可以利用数组reduce,每次返回一个promise,目标结构如下
Promise.resolve()
.then(() => {
deleteFile(1)
}).then(() => {
deleteFile(2)
}).then(() => {
deleteFile(3)
}).then(() => {
deleteFile(4)
})
//...
故有,写法二
function handler2(files) {
let index = 0;
return files.reduce(async(prev, cur) => {
return prev.then(await deleteFile.bind(null, index++))
//这是下面这种的简化形式
// return prev.then(async() => {
// return await deleteFile(index++);
// })
}, Promise.resolve())
}
这两种写法都挺好的,缺少点流程控制的感觉吧,于是for await of 登场了。
先了解一下generator ,简单理解generator函数就是,第一次调用它会返回一个可迭代对象,但并不执行函数里的代码,后面依次调用这个对象的next方法,就会执行 yield 关键字 前面的代码。
可迭代对象的好处就是,这把一个函数里面的执行权交给了外部,我们可以随时停止,也可以随时调用next再恢复执行。
写法三
function* createObject(files) {
// 怎么写不重要,这里目的根据files个数,生成多少个yield语句
// 相当于 yield deleleFile(0)
// yield deleleFile(1) yield deleleFile(2)...
for (const index in files) {
yield deleteFile(parseInt(index));
}
}
//生成一个可迭代对象
let object = createObject(files);
async function handler3() {
// 遍历该对象,就是依次调用 yield后面的代码
for await (const iterator of object) {
}
}
handler3()
怎么理解可迭代对象?其实没啥,它就是一个对象,之所以他能迭代,普通对象不能迭代,就是因为它多了个特殊的属性,属性名叫Symbol.iterator,值为一个函数,然后就是generator函数,所以下面这种写法和上面是等价的
let object = {
}
object[Symbol.iterator] = function*() {
for (const index in files) {
yield deleteFile(parseInt(index));
}
}
async function handler3() {
// 遍历该对象,就是依次调用 yield后面的代码
for await (const iterator of object) {
}
}
handler3()
以后遇到需要控制异步流程,可以优先想到用迭代器,这样看起来很清晰。
个人感觉这3种写法,优先级:迭代器>回调>reduce合成
迭代器清晰流畅就不用说了,回调写法看起来也还好,reduce合成属于装逼技巧,但是不能那么直观地看出控制流程。
本文地址:https://blog.csdn.net/illusion_melody/article/details/109265717
上一篇: 10个python爬虫入门实例(小结)
推荐阅读
-
ES6中的迭代器、Generator函数及Generator函数的异步操作方法
-
JS异步编程 (2) - Promise、Generator、async/await
-
详谈ES6中的迭代器(Iterator)和生成器(Generator)
-
一篇文章彻底搞懂Python中可迭代(Iterable)、迭代器(Iterator)与生成器(Generator)的概念
-
Python之生成器(generator)和迭代器(Iterator)
-
异步迭代器,generator,for await of
-
Python生成器(generator)与迭代器(iterator)
-
详解nodejs中的异步迭代器
-
JS异步编程 (2) - Promise、Generator、async/await
-
详谈ES6中的迭代器(Iterator)和生成器(Generator)