我有一个异步获取数据库行的函数,并为每行调用一个回调函数。我正在尝试编写一个包装器,该包装器是一个生成器函数,每次返回一行时都会产生收益,但是我没有看到如何正确产生收益。
原始代码如下:
db.each(query, (err, row) => {
// do something here with row
}, () => {
// called after the last row is returned
})
我熟悉生成器的工作原理,但是收益似乎属于生成器函数本身,而不是匿名函数。因此,我认为类似的方法将无效:
function* dbEach(db, query) {
db.each(query, (err, row) => {
yield row
})
}
当我实际尝试 时,出现错误“意外标识符”。
我进一步看了一下,看来ES2018现在具有异步迭代器,应该可以实现这一点。但是,在我已经有多次被调用的回调的情况下,我难以理解如何正确使用异步迭代器。
答案 0 :(得分:3)
您可以使生成器async
,然后使await
成为所有行都可以解析的Promise(这样,您就可以在{{1}的顶层引用一个rows
变量}),然后可以产生该dbEach
数组中的每一行:
rows
用于:
async function* dbEach(db, query) {
const rows = await new Promise((resolve, reject) => {
const rows = [];
db.each(query, (err, row) => {
if (err) reject(err);
else rows.push(row);
}, () => resolve(rows));
});
for (const row of rows) {
yield row;
}
}
for await (const row of dbEach(...)) {
// do something
}
似乎是为在每一行上运行一个回调而设计的,这对于使用生成器在此处尝试完成的操作而言并不是最佳选择-如果可能的话,如果有数据库中的一种方法,该方法可让您获取行的 array ,例如:
.each
尽管如此,我认为生成器在这里没有多大帮助-您最好async function* dbEach(db, query) {
const rows = await new Promise((resolve, reject) => {
db.getAllRows(query, (err, rows) => {
if (err) reject(err);
else resolve(rows);
});
});
for (const row of rows) {
yield row;
}
}
一个Promise解析为行,并同步遍历行:
await