The Node.js sqlite3 package has a method each that applys a callback for each row of a query result. How to write an async generator wrapper so that the following code could work?
More analyses so that SO is happy: The each method should be called only once for one query. Each apply of the row callback should yield a new Promise for the outer queryEach function. The problem is: yield statement in the callback is for the callback not the queryEach function.
import assert from 'assert';
import sqlite3 from 'sqlite3';
class Db {
db = new sqlite3.Database(':memory:');
async createTable(){
return new Promise((resolve,reject)=>{
this.db.run('CREATE TABLE tb(id INTEGER PRIMARY KEY AUTOINCREMENT,num INTEGER)',
(err)=>{
if(err) reject(err);
else resolve();
});
});
}
async insert(num){
assert(typeof(num)==="number");
return new Promise((resolve,reject)=>{
this.db.run(`INSERT INTO tb VALUES(NULL,${num})`,(err)=>{
if(err) reject(err);
else resolve();
});
});
}
// todo: an async generator wrapper, yield row object, return number
async* queryEach(){
this.db.each('SELECT * FROM tb',(err,row)=>{
// on each row
},(err,count)=>{
// on complete
});
}
async close(){
return new Promise((resolve,reject)=>{
this.db.close((err)=>{
if(err) reject(err);
else resolve();
});
});
}
}
async function main(){
const db = new Db();
await db.createTable();
await db.insert(2);
await db.insert(3);
await db.insert(4);
// print table using callback for each row
db.db.each('SELECT * FROM tb',(err,row)=>{
if(err) console.error(err);
else console.log(`row(${row.id},${row.num})`);
},(err,count)=>{
if(err) console.error(err);
else console.log(`over, count=${count}`);
});
// print using for await loop
for await (const row of db.queryEach()){
console.log(row);
}
await db.close();
}
main();