NodeJS - код внутри асинхронной функции c выполняется не по порядку - PullRequest
0 голосов
/ 22 февраля 2020

У меня проблема с веридом. Что я хочу сделать, так это то, что при вызове API я хочу сделать запрос к postgresql db с массовой вставкой. Сначала я выполняю l oop, который читает файл и извлекает из него данные для формирования массива значений. Затем я хочу сгенерировать массовый запрос вставки с помощью библиотеки pg-обещания. Но когда код выполняется, я получаю то, что он пытается сгенерировать запрос еще до того, как l oop запускается, и выдает ошибку о пустом массиве. Что за?

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);

Я удалил детали, но я надеюсь, что это предоставляет достаточно информации. Я пытался поместить консольные журналы до, в и после l oop, и сначала записывается материал до и после l oop, выдается ошибка, а затем l oop выполняется и регистрирует вещи. Я что-то не понимаю или что-то упускаю?

Ответы [ 2 ]

2 голосов
/ 22 февраля 2020

Просто сделать функцию async ничего не делает для вас sh здесь. Вы должны выяснить, какие асинхронные операции вы можете 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 do c.


You также совсем не нужно использовать 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);
    });
}
1 голос
/ 22 февраля 2020

Когда вы звоните rd.on(), вы просто устанавливаете событие с обратным вызовом, который будет вызываться при возникновении события линии. Все, что делает ваш код - это устанавливает обратный вызов, а затем переходит к остальной части кода, которая затем пытается вставить значения в базу данных. Вам нужно переместить код, который вставляется в базу данных, внутри функции обратного вызова вашего rd.on() после того, как вы пропустите все свои значения oop и добавите их в массив.

Однако я не знакомо, что это за строка в случае файла. Если это действительно строка за строкой для файла, то вы, очевидно, не сможете выполнить массовую вставку туда. В этот момент я предлагаю переместить этот шаг в свою собственную асинхронную функцию и await результат этой функции перед выполнением вставки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...