如何在 node.js 中等待流式传输 sql 查询

How to await a streaming sql query in node.js

我需要调出一个运行 sql 查询的函数,具有行级功能,并在继续之前等待整个过程。

函数代码:

const sql = require('mssql')

exports.doit = ()=>{
    const pool1 = new sql.ConnectionPool(dbConfig);
    const pool1Connect = pool1.connect();

    pool1.on('error', err => {
        console.error('error occurred on pool')
    })
    await pool1Connect
    try {
        const request = pool1.request();
        request.stream = true;
        request.query('select * from dbo.user');
        request.on('row', async orow => {
            console.log('outer row');
            const innerPool = new sql.ConnectionPool(dbConfig);
            const innerConnection = innerPool.connect();
            innerPool.on('error', err => {
                console.error('error occurred on pool')
            });
            const iConnection = await innerConnection;
            connections.push(iConnection);

            const innerRequest = innerPool.request();
            innerRequest.stream = true;
            var iquery = 'select * from dbo.order where userId='+ orow.userId
            innerRequest.query(iquery);

            innerRequest.on('row', async irow => {
                console.log(`User: ${orow.userId} Order: ${irow.orderId}`);
            });

            innerRequest.on('done', async () => {
                console.log('inner done');
                iConnection.close();
            });
        });
        request.on('done', async () => {
            console.log('outer done');
        })
    } catch (err) {
        console.error('SQL error', err);
    }
    sql.on('error', err => {
        // ... error handler
    })
}

然后像这样调用上面的函数:

var doit = require('./testmeHandler.js').doit;

 doit()
 .then(()=>{
     console.log("I AM DONE");
 });

await doit();
console.log('I AM DONE');

你明白了...

但真正发生的是,函数被调用,然后是 'I AM DONE',然后是所有 sql 调用的结果。

有人可以帮我把 'I AM DONE' 放在底部吗?还在习惯 async/await 和承诺。

谢谢

不知怎的,我相信你把它搞得有点混乱了。

使用这个

exports.doit = async ()=>
{
const request = new sql.Request(conn)
let records = await request.query('select * from dbo.user')

records.forEach(async r=>{
    try{
        // do something
        const inner = new sql.Request(conn)
        let recordInner = await request.query(innerQuery)
        recordInner.forEach(async r=>{//do some stuff})
        inner.close()
    }
    catch(err){
            //do something with the error
    }
    records.close()
})
}

执行:

async execute(){
    const result = await doit()
    return result
}

execute()

虽然我根本不知道你为什么要使用两个连接。只需尝试使用 JOINWHERE 子查询编写更明确的查询。您可以在单个查询中实现所有这些,而不是使用嵌套连接。 SQL虽然有点老,但是真的很给力

select * from dbo.order WHERE userId IN (SELECT userId FROM dbo.user)

对我来说更有意义。但是,无论你的船如何漂浮。

关于子查询的更多信息:https://www.dofactory.com/sql/subquery

在尝试让调用者同步工作一段时间后,我放弃并重新编写了使用常规查询(不是流式查询)的方法,并实现了我自己的 paging/throttling控制内存使用。现在效果很好!

我正在使用连接池来允许子查询和其他进程在一批结果中异步发生。

我会post更新代码。