我想要这样的功能:
export async function* iterateDir(dir: string) {
let list = await fs.readdir(dir); // fs-promise implementation of readdir
for (let file of list) {
yield file;
}
}
我会用的是:
for (let file in iterateDir(dir)) {
processFile(file);
}
这不起作用,因为函数不能同时是异步和生成器。
如何构建代码以实现相同的目标?
await fs.readdir
更改为回调,我假设外部for..of循环不会等待。iterateDir()
会很慢。答案 0 :(得分:13)
TypeScript 2.3 - tracked issue
支持此功能它引入了一些新类型,特别是:
interface AsyncIterable<T> {
[Symbol.asyncIterator](): AsyncIterator<T>;
}
但最重要的是它还引入了for await ... of
for await (const line of readLines(filePath)) {
console.log(line);
}
其中
async function* readLines(path) {
//await and yield ...
}
请注意,如果您想尝试此操作,则需要配置typescript以让它知道您具有运行时支持(将“esnext.asynciterable”添加到lib
列表)您可能需要填充{ {1}}。见TS2318: Cannot find global type 'AsyncIterableIterator' - async generator
答案 1 :(得分:0)
未来值流称为Observable
。所以最自然的是使用像RxJS或most.js这样的库。如果您不想仅使用一次新的复杂库,请使用旧的方法进行回调:
const path = require("path");
const fs = require("mz/fs");
async function listDirectory(dirName, cb, level = 0) {
for (let fileName of await fs.readdir(dirName)) {
let absName = path.resolve(dirName, fileName);
let isDirectory = (await fs.stat(absName)).isDirectory();
cb({ level, fileName });
if (isDirectory) {
await listDirectory(absName, cb, level + 1);
}
}
}
listDirectory(".", ({ level, fileName }) => {
console.log(" ".repeat(level) + fileName);
});
如果您尝试将回调转换为更好的抽象,您迟早会重新发现RxJS。它类似于将一次性回调转换为承诺。