如何使用 Node fs 构建异步流

How to structure async flow using Node fs

我无法让许多异步操作的流程正确进行。正如我下面的代码所示,outside readFile 首先打印到控制台,然后 namesyears 接下来打印,最后 in readFile,当我想要的时候整个 readFile/forEach 处理之前发生。

const fs = require('fs')
const names = {}
const years = {}

fs.readdir('./namesData', (err, files) => {
    files.forEach(file => {
        var year = file.substr(3, 4)
        var yearObj = {}
        fs.readFile(`./namesData/${file}`, 'utf8', (err, data) => {
            console.log('in readFile')
            if (err) throw new Error(err)
            var arr = data.split('\n')
            arr.forEach(record => {
                var recordArray = record.trim().split(',')
                var name = recordArray[0]
                var gender = recordArray[1]
                var score = recordArray[2]
                // populate 'names' object
                var nameObj = {year: year, gender: gender, score: score}
                if (names.hasOwnProperty(name)) {
                    names[name].push(nameObj)
                } else {
                    names[name] = [nameObj]
                }
                // populate 'years' object & add to yearObj and then years object
                var yearNameObj = {gender: gender, score: score}
                if (yearObj.hasOwnProperty(name)) {
                    yearObj[name].push(yearNameObj)
                } else {
                    yearObj[name] = [yearNameObj]
                }
            })
        })
        console.log('outside readFile')
        years[year] = yearObj
    })
    console.log(names)
    console.log(years)
})

我试过这种方法。似乎可以满足您在循环后打印 namesyears 的需要。

'use strict';

let _ = require('lodash');
const fs = require('fs');

function readFile(file) {
  try {
    console.log('in readFile');
    return fs.readFileSync(`./namesData/${file}`, 'utf-8');
  } catch (err) {
    console.log('err ', err.stack);
    return '';
  }
}

fs.readdir('./namesData', (err, files) => {
  let details = _.map(files, (file) => {
    let data = readFile(file);
    let year = file.substr(3, 4);
    return _.map(data.split('\n'), (row) => {
      if (_.isEmpty(row)) {
        return;
      }
      let words = row.trim().split(',');
      return {
        year: year,
        name: words[0],
        gender: words[1],
        score: words[2]
      };
    });
  });
  console.log('names', _.groupBy(details, 'name'));
  console.log('years', _.groupBy(details, 'year'));
});

使用硬编码 details 数组进行测试

let details = [{
  year: 1998,
  name: 'A',
  gender: 'M',
  score: 20
}, {
  year: 1998,
  name: 'B',
  gender: 'M',
  score: 21
}, {
  year: 1999,
  name: 'A',
  gender: 'M',
  score: 100
}, {
  year: 1999,
  name: 'A',
  gender: 'M',
  score: 80
}];