【问题标题】:NodeJS make promise wait for completion of foreach loopNodeJS 承诺等待 foreach 循环的完成
【发布时间】:2020-04-19 19:19:24
【问题描述】:

我有一个 NodeJS 脚本,它为用户调用 API,为每个用户获取多个数据并将其全部写入本地文件。将所有数据写入文件后,我正在尝试将该文件上传到服务器。问题是应该上传文件的代码在文件完全填充之前被执行。代码写在下面。我不知道如何让 promise 等待第一个函数完成。

var fs = require('fs');
var server = require('some-server');
var service = require('./some-service.js');
var moment = require('moment-timezone');
var csvWriter = require('csv-write-stream');
var writer = csvWriter({
sendHeaders: false
});

var users = require('./some-users')
writer.pipe(fs.createWriteStream('myFile' + '.txt'))

service.login().then(function (response) {

users.forEach(function (user) {

    service.getSpecificUser(user).then(function (response) {

        var myUser = JSON.parse(response)
        service.getDataForUser(user.Info).then(function (response) {
            var userData = JSON.parse(response);
            if (userData.IsValid) {
                userData.AdditionalInfo.forEach(function (additionalInfo) {
                    service.getAdditionalInfo(myUser.Info, userData.data).then(function (response) {

                        //Collect additional info and combine final results to write into file
                        // write to output csv file
                        writer.write({
                            //write information that is of interest
                        })

                    }, function (error) {
                        console.log('error getting additional data', error);
                    })
                }
                )
            }
        }, function (error) {
            console.log('error getting user data', error)
        })
    }, function (error) {
        console.log('error', myUser, error)
    })
});
}, function (error) {
 console.log('not logged', response);
}).then(function () {
//perform uploading to server
var fpath = 'path of file that contains downloaded data'
console.log("Trying to upload to file: " +fpath)
service.UploadFile(fpath, function (error, result, response) {
    if (!error) {
        console.log("Uploaded " + name);
    }
    else {
        console.log(error);
    }

})
})

任何帮助将不胜感激。

【问题讨论】:

  • javascript 的哪一部分应该最后调用? writer.write() 有回调,还是返回 Promise
  • @guest271314 last函数需要上传文件到服务器,需要最后调用
  • 您的 .then 回调没有返回任何内容,因此它们会在调用后立即解析(未定义)。正如 Bergi 指出的那样,带有 Promises 的 .forEach 没有什么意义 - 不确定您不能将 .forEach 与 Promises 一起使用的陈述,因为可以,您只需要编写比使用更复杂的代码.mapPromise.all 例如 - 或者使用像 bluebird 这样的库,它有 Promise.map 这是 Array#map + Promise.all 的糖
  • 如果您要捕获/记录中间错误,请不要忘记重新抛出它们,否则承诺链将(尝试)沿着其成功路径前进。

标签: javascript node.js callback promise


【解决方案1】:

您可以将Promise.all()Array.prototytpe.map() 替换为.forEach()csv-write-steam 的文档似乎使用 .end() 来完成调用 .write() 最后 .then()

  service.login().then(function(response) {
    return Promise.all(users.map(function(user) {
      return service.getSpecificUser(user).then(function(response) {
        var myUser = JSON.parse(response)
        return service.getDataForUser(user.Info).then(function(response) {
          var userData = JSON.parse(response);
          if (userData.IsValid) {
            return Promise.all(userData.AdditionalInfo.map(function(additionalInfo) {
              return service.getAdditionalInfo(myUser.Info, userData.data).then(function(response) {
                //Collect additional info and combine final results to write into file
                // write to output csv file
                writer.write({
                  //write information that is of interest
                });
              })
            }))
          }
        })
      })
    }));
  })
  .then(function() {
   writer.end();
    //perform uploading to server
    var fpath = 'path of file that contains downloaded data'
    console.log("Trying to upload to file: " + fpath)
    service.UploadFile(fpath, function(error, result, response) {
      if (!error) {
        console.log("Uploaded " + name);
      } else {
        console.log(error);
      }

    })
  })
  .catch(function(e) {
    console.log(e)
  })

【讨论】:

  • 你不能在那里打电话给writer.end()。写入过程是同步的,您无需等待任何内容。 writer.end() 不返回承诺。即使是这样,您也不需要Promise.resolve
  • 为什么出错了还要上传文件?您应该将.catch 移到最后。
  • @Bergi 没有尝试过csv-write-stream。正要读剧本本身。 .end() 不需要调用?将 .catch() 移至链接到 .then()
  • 也许它确实需要在最后调用,甚至可能需要等待某种流结束事件,但肯定不应该在每次写入后调用它。
  • @Bergi 文档没有描述返回的内容。现在必须做的事情,但今天晚些时候会阅读实际的脚本。现在将.end() 移动到最后一个.then()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-26
  • 2019-05-31
  • 2018-04-25
  • 2016-09-09
相关资源
最近更新 更多