【问题标题】:Node.js wait for all files read in the loopNode.js 等待循环中读取的所有文件
【发布时间】: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] 都不适合我。

【问题讨论】:

    标签: javascript node.js


    【解决方案1】:

    我会怎么做:

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

    类似的东西:

    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);放在哪里?
    猜你喜欢
    • 1970-01-01
    • 2021-06-03
    • 2012-09-30
    • 2021-10-18
    • 2017-09-12
    • 2019-07-28
    • 2022-06-23
    • 2023-01-20
    相关资源
    最近更新 更多