首页 > 解决方案 > NodeJS - 异步函数内的代码乱序执行

问题描述

我有一个奇怪的问题。我想要做的是,在调用 api 时,我想通过批量插入向 postgresql db 发出请求。首先,我执行读取文件并从中提取数据以形成值数组的循环。然后,我想用 pg-promise 库生成一个批量插入请求。但是当代码执行时,我得到的是它试图在循环开始之前生成一个请求,并且它抛出一个关于空数组的错误。什么?

async import(req, res) {
    var rd = readline.createInterface({
       input: fs.createReadStream('.../file.csv'),
       console: false
     });

    const createQuery = `INSERT INTO 
          table('columns') 
          VALUES ?`;
    const values = [];
    rd.on('line', function(line) {
       //stuff
         values.push({
           //stuff
         });
       }
     });
    const cs = new pgp.helpers.ColumnSet(['columns'], {table: 'table'});
    const query = pgp.helpers.insert(values, cs);

我已经删除了细节,但我希望这能提供足够的信息。我尝试在循环之前、之中和之后放置控制台日志,首先,记录循环之前和之后的内容,抛出错误,然后执行循环并记录内容。我不明白或错过了什么吗?

标签: javascriptnode.jspostgresql

解决方案


仅仅制作函数async本身并不能为你完成任何事情。您必须找出可以进行哪些异步操作await才能序列化您的异步操作。

在最新版本的 node.js 中,您可以使用for await ()readline 接口中带有异步迭代器的结构来处理所有行。

async import(req, res) {
    var rd = readline.createInterface({
       input: fs.createReadStream('.../file.csv'),
       console: false
     });

    const createQuery = `INSERT INTO 
          table('columns') 
          VALUES ?`;
    const values = [];
    for await (const line of rd) {
        values.push({...})
    }
    const cs = new pgp.helpers.ColumnSet(['columns'], {table: 'table'});
    const query = pgp.helpers.insert(values, cs);
}

仅供参考,您可以在readline doc中看到一个示例。


您也根本不需要使用async,因为您只需将最后两行放入事件的事件侦听器即可解决它close

import(req, res) {
    var rd = readline.createInterface({
       input: fs.createReadStream('.../file.csv'),
       console: false
     });

    const createQuery = `INSERT INTO 
          table('columns') 
          VALUES ?`;
    const values = [];
    rd.on('line', function(line) {
       //stuff
         values.push({
           //stuff
         });
       }
     }).on('close', () => {
        // done with all line processing here
        const cs = new pgp.helpers.ColumnSet(['columns'], {table: 'table'});
        const query = pgp.helpers.insert(values, cs);
    });
}

推荐阅读