Node.js:按定义的顺序返回 promise

标签 node.js csv promise fast-csv

我有数百个 JSON 文件,需要按照定义的顺序进行处理,并按照与 JSON 文件中相同的顺序将内容写回为 CSV:

  1. 编写带标题的 CSV 文件
  2. 收集要处理的 JSON 文件数组
  3. 读取文件并返回包含所需信息的数组
  4. 附加在 #1 下创建的 CSV 文件以及信息
  5. 继续第 3 步处理下一个 JSON 文件
'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 的各种组合,导致未决的 Promise 或混合的 CSV 文件。

这是我对 Node.js Promises 的第一次尝试,因此非常感谢关于如何正确执行此操作的每一个输入。非常感谢。

最佳答案

此代码应按顺序处理您的文件,我们将使用 async/await 和 for .. of 依次循环:

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

关于Node.js:按定义的顺序返回 promise ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58007062/

相关文章:

javascript - 将 Node.js/Socket.io 放到网站上

node.js - 如何恢复多个平台的 Node 模块?

PHP 加载数据文件不起作用

php - 为什么我尝试使用 Google Drive SDK 插入 CSV 文件时会收到错误 400?

regex - 如何对 2 列 CSV/Notepad++ 数据进行排序?

javascript - 控制 Promise 执行顺序

javascript - 稍后在链中使用 Promise 的响应

node.js - 使用异步并行进行多个 Mongoose 调用

Javascript promise 意外的执行流程

javascript - PDF A4 页面中的网站内容不响应