与异步/等待的竞争条件

时间:2018-06-13 06:25:03

标签: javascript node.js

我遇到了一个问题(竞争条件),我似乎无法过去。

我在下面的console.log语句中添加了两条注释。您可以看到第二个被调用,这是一个问题因为var是空的。我有异步并等待但仍不确定为什么会发生这种情况

router.put("/", async (req, res, next) => {
   var s3 = new AWS.S3();

  var params = {
    Bucket: "bucket1",
    Delimiter: '/',
    Prefix: req.body.params + '/'
  };

  var files= [];
  var tmp = '';

await s3.listObjectsV2(params, function(err, data) {

  for(var item in data.Contents){
      for(var anotherItem in data.Contents[item]){
        if(anotherItem == "Key"){
          tmp = data.Contents[item][anotherItem]
          var res = tmp.replace(req.body.params + '/', '')
          files.push(res)
        }
      }
   }
   this.allFiles = files
   console.log('allFiles - First', this.allFiles);  //this is logged second and has the correct data array

});

  console.log('allFiles - Second', this.allFiles);  //this gets logged first and is empty
  return res.send(this.allFiles);
});

3 个答案:

答案 0 :(得分:1)

你只能等待一个承诺。

s3.listObjectsV2似乎接受了回调而没有返回承诺。

你需要将它包装在一个承诺中。

答案 1 :(得分:1)

await仅适用于Promises。看起来listObjectsV2是基于回调的,而不是基于Promise的 - 你必须明确地将其转换为Promise才能await它,你也可能拥有Promise {1}}直接解析为allFiles

const allFiles = await new Promise((resolve, reject) => {
  s3.listObjectsV2(params, function(err, data) {
    if (err) reject (err);
    const files = [];
    for(var item in data.Contents){
      for(var anotherItem in data.Contents[item]){
        if(anotherItem == "Key"){
          tmp = data.Contents[item][anotherItem]
          var res = tmp.replace(req.body.params + '/', '')
          files.push(res)
        }
      }
    }
    console.log('allFiles - First', files);
    resolve(files);
  });
});
console.log('allFiles - Second', allFiles);
return res.send(allFiles);

答案 2 :(得分:0)

await关键字需要承诺才能使用,但使用回调调用该函数不会给您一个。相反,请使用builtin method to get a promise

router.put("/", async (req, res, next) => {
  var s3 = new AWS.S3();
  var params = {
    Bucket: "bucket1",
    Delimiter: '/',
    Prefix: req.body.params + '/'
  };
  var files = [];

  var data = await s3.listObjectsV2(params).promise();
  //  ^^^^^^^                             ^^^^^^^^^^^^
  for (var item in data.Contents) {
    for (var anotherItem in data.Contents[item]) {
      if (anotherItem == "Key") {
        var tmp = data.Contents[item][anotherItem]
        var res = tmp.replace(req.body.params + '/', '')
        files.push(res)
      }
    }
  }
  this.allFiles = files
  console.log('allFiles - First', this.allFiles);  //this is logged and has the correct data array
  return res.send(this.allFiles);
});