在Node中异步读取文件

时间:2017-08-16 13:56:40

标签: javascript node.js asynchronous

我正在尝试加载两个文件并异步执行相同的操作。我的代码工作正常,因为我能够加载文件并对它们执行操作。但是,我正在写两次相同的功能。关于如何使这种异步的任何想法?

var arrayTest =  require('./data1.json');

arrayTest.data.forEach(function(str) {
  var newStr = str.replace(/"[^"]*"/g, function(match) {
    return match.split('').reverse().join('');
  });
  console.log(newStr);
});


var arrayTest2 =  require('./data2.json');

arrayTest2.data.forEach(function(str) {
  var newStr = str.replace(/"[^"]*"/g, function(match) {
    return match.split('').reverse().join('');
  });
  console.log(newStr);
});

4 个答案:

答案 0 :(得分:0)

尝试使用节点js fs模块。在这种情况下,每次从readFile(对于每个文件)调用回调时,都会执行操作。

const fs = require('fs');

function readFilesAsync(files, action) {

  files.forEach(file => {
    // Use node fs to read files async
    fs.readFile(file, action);

  });

}

// Your custom function
function replaceString(err, str) {
  if (err) throw err;
  var newStr = str.replace(/"[^"]*"/g, function(match) {
    return match.split('').reverse().join('');
  });
  console.log(newStr);
}

readFilesAsync(['./data1.json', './data2.json'], replaceString);

答案 1 :(得分:0)

我会把它改成那样的东西。使用promises处理异步IO,并使用1函数,以避免代码重复。

'use strict';

const fs = require('fs');
const files_paths = ['./data1.js', './data2.js'];

Promise.all(files_paths.map((path) => {
    return new Promise((resolve) => {
        fs.readFile(path, 'utf-8', (error, data) => {
            resolve(data.split(',').map((str) => {
                return str.replace(/"[^"]*"/g, (match) => {
                    return match.split('').reverse().join('');
                });
            }));
        });
    });
})).then((results) => {
    console.log(results);
});

答案 2 :(得分:0)

要异步加载文件,您可以使用fs.readFile(),然后使用JSON.parse()替换同步require()自行手动解析它们。所以,这是一个异步加载文件然后将它们解析为Javascript的函数:

// returns a promise
loadJsonAsync(file) {
    return new Promise((resolve, reject) => {
        fs.readFile(file, (err, data) => {
            if (err) {
                reject(err);
            } else {
                resolve(JSON.parse(data));
            }
        });
    });
}

注意,文件加载将是异步的。 JSON解析将是同步的。

然后,您可以在执行处理的函数中使用它:

function loadAndProcess(f) {
    return loadJsonAsync(f).then(arr => {
        for (let str of arr.data) {
            const newStr = str.replace(/"[^"]*"/g, function(match) {
                return match.split('').reverse().join('');
            });
            console.log(newStr);
            // do something with newStr here
        }
    }).catch(err => {
        console.log(err);
        throw err;
    });
}

然后你可以像这样运行其中两个:

Promise.all([loadAndProcess("./data1.json"),loadAndProcess("./data2.json")]).then(data => {
    // both are done here
 }).catch(err => {
    // error here
 });

如果您希望执行JSON解析的同步代码和替换循环也是异步的,那么您必须将该代码移动到子进程,然后在完成时将结果传回主进程,因为那里在nodejs中没有办法让同步操作在同一个进程中成为异步操作。

答案 3 :(得分:-1)

const arrayTest = require('./data1.json');
const arrayTest2 = require('./data2.json');

doJob(arrayTest);
doJob(arrayTest2);

function doJob(arr) {
  arr.data.forEach(function(str) {
    const newStr = str.replace(/"[^"]*"/g, function(match) {
      return match.split('').reverse().join('');
    });
    console.log(newStr);
  });
}

如果你想在之前合并数组:

doJob(arrayTest.concat(arrayTest2);

<强>更新 正如我之前已经告诉过你的那样,在大多数情况下,这种“异步”流程是无用的。异步流不是并行流。

如果您拥有非常大的文件,真正的利润可能来自使用子进程。如果是这样,您可以收集更多knowledge here