Node.js: вернуть обещания в определенном порядке. - PullRequest
1 голос
/ 19 сентября 2019

У меня есть несколько сотен файлов JSON, которые необходимо обработать в определенной последовательности и записать содержимое в формате CSV в том же порядке, что и в файлах JSON:

  1. Записать файл CSV с помощьюheader
  2. Собрать массив JSON-файлов для обработки
  3. Прочитать файл и вернуть массив с необходимой информацией
  4. Добавить CSV-файл, созданный в # 1, с помощьюинформация
  5. Перейдите к следующему файлу JSON на шаге № 3
'use strict';
const glob = require('glob');
const fs = require('fs');
const fastcsv = require('fast-csv');
const readFile = require('util').promisify(fs.readFile);

function writeHeader(fileName) {
  return new Promise((resolve, reject) => {
    fastcsv
      .writeToStream(fs.createWriteStream(fileName), [['id', 'aa', 'bb']], {headers: true})
      .on('error', (err) => reject(err))
      .on('finish', () => resolve(true));
  });
}

function buildFileList(globPattern) {
  return new Promise((resolve, reject) => {
    glob(globPattern, (err, files) => {
      if (err) {
        reject(err);
      } else {
        resolve(files);
      }
    });
  });
}

function readFromFile(file) {
  return new Promise((resolve, reject) => {
    readFile(file, 'utf8', (err, data) => {
      if (err) {
        reject(err);
      } else {
        const obj = JSON.parse(data);
        const key = Object.keys(obj['776'])[0];
        const solarValues = [];
        obj['776'][key].map((item, i) => solarValues.push([i, item[0], item[1][0][0]]));
        resolve(solarValues);
      }
    });
  });
}

function csvAppend(fileName, rows = []) {
  return new Promise((resolve, reject) => {
    const csvFile = fs.createWriteStream(fileName, {flags: 'a'});
    csvFile.write('\n');
    fastcsv
      .writeToStream(csvFile, rows, {headers: false})
      .on('error', (err) => reject(err))
      .on('finish', () => resolve(true));
  });
}

writeHeader('test.csv')
  .then(() => buildFileList('data/*.json'))
  .then(fileList => Promise.all(fileList.map(item => readFromFile(item))))
  .then(result => Promise.all(result.map(item => csvAppend('test.csv', item))))
  .catch(err => console.log(err.message));

Примеры JSON:

https://gist.github.com/Sineos/a40718c13ad0834b4a0056091e3ac4ca

https://gist.github.com/Sineos/d626c3087074c23a073379ecef84a55c

Вопрос

Хотя код в основном работает, моя проблема заключается в том, что CSV записывается не в определенном порядке, а перемешивается, как васинхронный процесс.

Я пробовал различные комбинации с и без Promise.all, что приводило либо к ожидающим обещаниям, либо к смешанному файлу CSV.

Это мой первый взгляд на обещания Node.js, поэтому каждый вводо том, как сделать это правильно, с благодарностью.Большое спасибо заранее.

1 Ответ

0 голосов
/ 19 сентября 2019

Этот код должен обрабатывать ваши файлы по порядку, мы будем использовать async / await и для ... цикла в последовательности:

async function processJsonFiles() {
    try {
        await writeHeader('test.csv');
        let fileList = await buildFileList('data/*.json');
        for(let file of fileList) {
            let rows = await readFromFile(file);
            await csvAppend('test.csv', rows);
        }
    } catch (err) {
        console.error(err.message);
    }
}

processJsonFiles();
...