我有一个生成器,其中包括查询数据库等操作,例如:
function* current(db) {
const items = await db.collection('...').find({ ... });
for (const item of items)
if (...) yield item;
}
这不是有效的语法。使用承诺和从then
中产生是不可能的。
那我该怎么办?我如何在生成器中使用异步操作?
我有一个生成器,其中包括查询数据库等操作,例如:
function* current(db) {
const items = await db.collection('...').find({ ... });
for (const item of items)
if (...) yield item;
}
这不是有效的语法。使用承诺和从then
中产生是不可能的。
那我该怎么办?我如何在生成器中使用异步操作?
在生成器(也称为异步生成器)中调用await
已经在Node v10+(2018年4月发布)和Chrome自v63以及Firefox v57开始本地支持。
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function getAsyncData() {
await sleep(1000); // simulate database/network delay...
return [1, 2, 3, 4, 5]; // ...then return some data
}
// async generator
async function* filterAsyncData() {
const items = await getAsyncData(); // await call in generator
for (const item of items)
if (item % 2) yield item;
}
(async function main() {
// for-await syntax
for await (const filteredItem of filterAsyncData())
console.log(filteredItem);
// classic iterator syntax
const fadIt = filterAsyncData();
while (true) {
const result = await fadIt.next(); // note await
if (result.done) break;
console.log(result.value);
}
}());
.next()
之前请记得使用await
。或者,自Node v9.2以来,新的for-await-of
语法已经可用,并且可以在不使用任何标志的情况下在Node v10中使用。您不能将async与生成器函数结合使用。话虽如此,在您的情况下,您很可能不想使用生成器,而是只需拥有一个async函数:
async function current(db) {
while (true) {
const latest = await db.collection('messages').findOne({}, {
sort: {
timestamp: -1
}
});
return smth;
}
}
当async
被转译时,生成器将会为您生成。
while (true)
循环没有意义,你的函数在第一次迭代中就会 return
。 - Bergi
async
与生成器函数结合使用。 - Bergi