How to write an async generator wrapper for nodejs sqlite3 method each?

Viewed 14

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();
0 Answers
Related