【问题标题】:Promise then block executing before completion of Post Request?承诺然后在完成发布请求之前阻止执行?
【发布时间】:2019-11-26 17:19:13
【问题描述】:

我正在使用 axios 向我的 Nodejs 后端发出 Post 请求,以使用 AWS S3 为我需要的特定数据提取 Urls(与问题不完全相关,但与上下文相关)。

在后端,我有一个包含 12 个条目的数组,初始化为每个元素的“测试”。然后我根据前端的 json 更新数组中的特定元素。在我更新一个这样的元素后,我立即 console.log 整个数组并且它正确地具有更新的数组。当我在返回后端之前最后一次 console.log 整个数组时,所有条目都是“测试”,但我知道这可能是因为 console.log 不是同步的。但是,当我将该数组返回到前​​端并 console.log 响应时,该数组仍然是全部 12 个“测试”,这让我相信在 Post 请求甚至完成之前执行“then”块(这令人困惑) .我不确定该怎么做,因为在前端进行其他数据验证之前我需要正确的数组。任何建议将不胜感激。

我尝试将发布请求放在单独的函数中并返回该承诺,但这也不起作用。

handleSubmit(event) {
event.preventDefault();
//other code before
let json=JSON.stringify(data);
let post_data={json_data:json}

 this.grabData(post_data)
  .then((response) => {
    console.log(response)
    var myObj = JSON.parse(response.data.json_data);
    console.log(myObj.length)
    var i;
    //Should output that certain elements have been changed, but all show up as 'test' still
    for (i = 0; i < 12; i++) {
      console.log("element " + i + " is: " + myObj[i])
    }
    this.state.urls = myObj;
    var z;
    for (z = 0; z < 12; z++) {
      if (this.state.urls[z] === "test") {
        this.state.urls.splice(z, 1);
        z = z - 1;
      }
    }
    //The state.urls should not be empty after the splicing, but it is because all elements are still 'test' 
    console.log("After splicing: " + this.state.urls)
  });
}

grabData(post_data) {
  return axios.post('/getCharts', post_data)
}

在后端:

  app.post('/getCharts', (req, res) => {
  var obj = JSON.parse(req.body.json_data)
  let getThese = req.body[0]
  var urls = ["test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test"];
  var i;
  var year = new Date().getFullYear();
  console.log(year)

  let jan = ''
  let feb = ''
  let mar = ''
  let apr = ''
  let may = ''
  let jun = ''
  let jul = ''
  let aug = ''
  let sep = ''
  let oct = ''
  let nov = ''
  let dec = ''

  for (i = 0; i < obj.length; i++) {
    if (obj[i] == 1) {
      key = 'charts/pieChart' + year + '-01-01.png'
      console.log(key)
      var params = {Bucket: bucketName, Key: key}

      s3.headObject(params, function (err, metadata) {
        if (!err) {
          urls[0] = s3.getSignedUrl('getObject', params);
        }
      });
    }
    if (obj[i] == 2) {
      key = 'charts/pieChart' + year + '-02-01.png'
      console.log(key)
      var params = {Bucket: bucketName, Key: key}

      s3.headObject(params, function (err, metadata) {
        if (!err) {
          urls[1] = s3.getSignedUrl('getObject', params);
        }
      });
    }
    if (obj[i] == 3) {
      key = 'charts/pieChart' + year + '-03-01.png'
      console.log(key)
      var params = {Bucket: bucketName, Key: key}

      s3.headObject(params, function (err, metadata) {
        if (!err) {
          urls[2] = s3.getSignedUrl('getObject', params);
          //This outputs a correctly updated array
          console.log(urls)
        }
      });
    }
    //This if block is repeated 12 times, up to obj[i] = 12, so removing for sake of simplicity
  }

  var i2;
  //This array prints out 12 'test' but I understand it's because console.log is executed async
  for (i2 = 0; i2 < 12; i2++) {
    console.log("urls" + i2 + " is: " + urls[i2])
  }

  let json=JSON.stringify(urls);

  let post_data={json_data:json}

  res.setHeader('Content-Type', 'application/json');
  res.send(post_data);
});

【问题讨论】:

  • 很难理解你在问什么。也许在代码中添加一些您期望的内容。但是在您的grabData(post_data) 请求中。你永远不会返回任何东西。如果您想将数据返回给客户端,您需要在grabData 末尾发送return this.state.urls
  • 感谢您的回复。我最初拥有它,所以它会执行 axios.post(...).then((response) => ...) 但我被告知尝试将发布请求放在单独的函数中并返回该承诺。所以,grabData 中的 return axios.post('/getCharts', post_data) 是为了返回我想的承诺。
  • 您能否包含您的/getCharts 函数。该函数似乎没有返回您期望的结果。
  • 刚刚编辑了 OP!
  • 您对服务器不只是返回一堆“测试”有多大信心?我很有信心。

标签: node.js reactjs asynchronous callback axios


【解决方案1】:

我的朋友,Obj for 循环是讨厌的代码哈哈.. for 循环的原因是只做一次。我清理了你的代码。它应该工作。但如果不是,这就是基本思想..

 app.post('/getCharts', (req, res) => {
  var obj = JSON.parse(req.body.json_data)
  let getThese = req.body[0]
  var urls = ["test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test"];
  var i;
  var year = new Date().getFullYear();
  console.log(year)

  let jan = ''
  let feb = ''
  let mar = ''
  let apr = ''
  let may = ''
  let jun = ''
  let jul = ''
  let aug = ''
  let sep = ''
  let oct = ''
  let nov = ''
  let dec = ''

        let uploads = 0;
    const finishedUpload = () => {
        uploads++;
        if (uploads === obj.length) {
              var i2;
              //This array prints out 12 'test' but I understand it's because console.log is executed async
              for (i2 = 0; i2 < 12; i2++) {
                console.log("urls" + i2 + " is: " + urls[i2])
              }

              let json=JSON.stringify(urls);

              let post_data={json_data:json}

              res.setHeader('Content-Type', 'application/json');
              res.send(post_data);
        }
    }

  for (i = 0; i < obj.length; i++) {
    const myKey = i+1;
    if (obj[i] == myKey) {
      key = 'charts/pieChart' + year + '-0' + myKey +'-0' + myKey +'.png'
      console.log(key)
      var params = {Bucket: bucketName, Key: key}

      s3.headObject(params, function (err, metadata) {
        if (!err) {
          urls[i] = s3.getSignedUrl('getObject', params);
          finishedUpload()
        }
      });
    }
  }

});

【讨论】:

  • 感谢您的回复。我尝试进行这些更改,但我仍然遇到同样的问题。您认为我需要更改前端代码中的任何内容吗?
  • 哇,好吧,我只是从你的答案中玩弄了一些小东西,它奏效了!非常感谢,你不明白我已经尝试修复它多久了哈哈。
猜你喜欢
  • 2018-05-09
  • 1970-01-01
  • 2022-11-28
  • 1970-01-01
  • 2021-07-23
  • 1970-01-01
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多