Неожиданное поведение при использовании модуля узла csv-parser - PullRequest
2 голосов
/ 07 мая 2019

Я пытаюсь получить заголовки файла csv в массив и пытаюсь использовать для этого csv-parser.Здесь я не могу понять две вещи:

1) Почему console.log в последней строке кода запускается раньше всего?Это также означает, что значение переменной, которую я пытаюсь записать, не определено.

2) Почему моя функция getFields не возвращает недавно заполненный массив заголовков?Я могу console.log массив результатов со всеми его новыми элементами изнутри функции, но на самом деле я не могу вернуть массив, полный элементов - он продолжает возвращать пустой массив.

Вот код:

const express = require('express')
const app = express()
const port = 3000
const csv = require('csv-parser')  
const fs = require('fs')

function getFields (filePath) {
  let results = [];
  fs.createReadStream(filePath)
    .pipe(csv())
    .on('headers', (headers) => {
      let values = Object.values(headers);
      values.forEach(function(element) {
        results.push(element);
      });
      console.log('I am actually getting results here: ', results);
      return results;
   });
}

const omg = getFields(thisIsAFilePath)
console.log('This console.log is firing before anything else: ', omg)

1 Ответ

0 голосов
/ 07 мая 2019

Ваш код использует асинхронный обратный вызов.Это означает, что обработчик события (функция (headers) => {...}) выполняется при возникновении события (в данном случае headers).Это происходит асинхронно, в то время как оставшийся скрипт продолжается.

Это означает, что происходит следующее:

  1. Функция объявлена ​​
  2. Функция вызывается, так как она возвращаетничего (даже не имеет оператора return), undefined хранится внутри omg
  3. Вызов console.log выполняется
  4. В какой-то момент в будущем событие headers сработает и выполнит функцию (headers) => { ... }

Так что, если вам нужны результаты, вам нужно поместить код в обратный вызов или вызвать функцию изнутри, например:

function handleHeaders(headers) {
  console.log(headers);
}

function getFields (filePath) {
  let results = [];
  fs.createReadStream(filePath)
    .pipe(csv())
    .on('headers', (headers) => {
      handleHeaders(headers);
   });
}

Альтернатива: Promise

Кроме того, вы можете использовать Promise API , который позволит писать ваш код следующим образом:

(async () => {
    function getFields(filePath) {
        return new Promise(resolve => {
            let results = [];
            fs.createReadStream(filePath)
                .pipe(csv())
                .on('headers', (headers) => {
                    let values = Object.values(headers);
                    values.forEach(function (element) {
                        results.push(element);
                    });
                    console.log('I am actually getting results here: ', results);
                    resolve(results);
                });
        });
    }

    const omg = await getFields(thisIsAFilePath)
    console.log('This console.log is firing before anything else: ', omg)
})();

Имейте в виду, код также выполняется асинхронно, он просто скрыт в форме Обещаний.

...