Node.js 等待循环中读取的所有文件

Posted

技术标签:

【中文标题】Node.js 等待循环中读取的所有文件【英文标题】:Node.js wait for all files read in the loop 【发布时间】:2018-08-02 01:03:50 【问题描述】:

我是 javascript/node.js 事件驱动范例的新手。

我需要在 forEach 之后停止 for 以确保所有文件都已被读取,然后我继续。在这种情况下我应该如何实现wait_for_all_files_read()

my_list.forEach(function(element) 
  fs.readFile(element.file_path, function(err, data)  
    if(err) throw err;
    element.obj=JSON.parse(data);
  );
);
wait_for_all_files_read(); <-----------
analyze(my_list)

[1] 或 [2] 都不适合我。

【问题讨论】:

【参考方案1】:

我会怎么做:

    Promisify fs.readFile(通过使用,例如 Bluebird) 将函数标记为异步 制作回调列表(my_list.map 而不是 forEach) “等待 Promise.all(myListOfCallbacks)” 等待后的下一行将在所有操作完成后执行

类似的东西:

const promisisfy = require('util')
const fs = require('fs')
const readFile = promisify(fs.readFile)

const fileNames = getFilenamesArray();

async function executeMe() 
  try 
    const arrayWithFilesContent = await Promise.all(
      fileNames.map(name => readFile(name))
    );
    return analyze(arrayWithFilesContent);
  
  catch (err) 
    handleError(err)
  


executeMe();

【讨论】:

readFIle 内部有一个回调。如何考虑? 当它被承诺时,它会返回承诺。我们可以使用 promise .then(或 await)而不是提供回调作为参数。 那么,我应该把if(err) throw err;element.obj=JSON.parse(data);放在哪里? 你可以删除 try/catch 块,而不是 Promise.all 会抛出错误。关于元素 - 你可以在 Promise.all 之后的循环中完成 我很困惑。【参考方案2】:

我可以建议您重写代码以实现承诺 - 这样处理起来会容易得多

const promisisfy = require('util')
const fs = require('fs')
const readFile = promisify(fs.readFile)

const fileNames = getFilenamesSomehow() // <-- returns array with path, e.g. ["./package.json", "/etc/hosts", "/etc/passwd"]

Promise.all(fileNames.map(name => readFile(name)))
.then(arrayWithFilesContent => analyze(arrayWithFilesContent))
.catch(err => handleError(err))

下一步你可以做什么 - 将代码移动到 async/await 函数中

UPD

假设您只需要读取一个文件,然后将其数据解析为 json 并以某种方式分析结果。

这种情况下你可以做下一步:

readFile(singleFileName)
.then(function (singleFileContent) 
   return JSON.parse(singleFileContent)
)
.then(function (singleFileContentInJson) 
   return analyze(singleFileContentInJson)
)
.catch(funciton (error) 
  //here you can process all errors from functions above: reading file error, JSON.parse error, analyze error...
  console.log(error)
)

然后假设您需要分析一堆文件

const fileNames = [...] // array with file names
// this create an array of promises, each of them read one file and returns the file content in JSON
const promises = fileNames.map(function (singleFileName) 
    return readFile(singleFileName)
    .then(function (singleFileContent) 
       return JSON.parse(singleFileContent)
    )
)

// promise all resolves (calls callback in 'then') all of promises in array are resolved and pass to then callback array with result of each promise
Promise.all(promises)
  .then(function (arrayWithResults) 
    return analyze(arrayWithResults)
  )
  // catch callback calls if one of promises in array rejects with error from the promise - so you can handle e.g. read file error or json parsing error here
  .catch(function (error) 
    //here you can handle any error
    console.log(error)
  )

尝试在谷歌上搜索一些文章来阅读 Promise 是如何工作的。 例如。你可以开始表单mdn article

【讨论】:

我可以用function(name) ...代替name =&gt; readFile(name)吗? readFile里面我有另一个回调,它是否也等待所有的内部回调? 不。 Promisify function 只是将已作为参数传递的函数与 promise 包装起来。 readFIle 内部有一个回调。如何考虑? 另外,我应该把if(err) throw err;element.obj=JSON.parse(data);放在哪里?

以上是关于Node.js 等待循环中读取的所有文件的主要内容,如果未能解决你的问题,请参考以下文章

Node.JS MySql 在循环中等待预期结果

Node.js 回调函数

Node Js

node js 回调函数

Node.js 回调函数

Node.js 回调函数