【问题标题】:Axios POST promise not working as expectedAxios POST 承诺未按预期工作
【发布时间】:2019-01-19 16:24:18
【问题描述】:

我有一个带有 Sequelize/mysql 的 react/node/express 应用程序。使用 Axios 进行 API 调用。

我需要做什么:

  1. 将配方发布到数据库
  2. 等待上述完成
  3. 再次获取配方表以使用新配方更新反应组件状态

目前发生了什么:

  1. 配方被发布到数据库
  2. GET 配方在 Promise 从 POST 中返回。因此,组件状态得到 设置为旧数据。

我尝试使用 async/await,但这并没有什么不同。

这里是删减的代码:

API.js:

addRecipe: async function(newRecipe) {
    let addRecipe = await axios.post('/api/recipes/new', newRecipe) 
    return addRecipe
},
getRecipes: function() {
    return axios.get('/api/recipes');
}

Recipes.js:

  import API from '../../utils/API';
  state = {
    dbRecipes: []
  }

  getRecipes = () => {
    API.getRecipes()
      .then(res => {
        this.setState({
          dbRecipes: res.data
        })
      })
  }

  handleFormSubmit = event => {
  event.preventDefault();
    API.addRecipe(formData).then(result => {
       this.getRecipes()
    })
  }

添加配方控制器:

exports.addRecipe = function (req, res) {
  const imgPath = req.file.path.replace('client/public','');
  db.Recipe.create({
    RecipeName: req.body.RecipeName,
    RecipeDescription: req.body.RecipeDescription,
    RecipeImage: imgPath
  }).then(function (newRecipe) {
    RecipeIngredients = JSON.parse(req.body.RecipeIngredients)
    var promises = [];
    for (var i = 0; i < RecipeIngredients.length; i++) {
      var RecipeId = newRecipe.dataValues.id;
      promises.push(
        db.RecipeAmount.create({
          Amount: RecipeIngredients[i].AmountForSmall,
          Size: 'sm',
          Type: 'smoothie',
          IngredientId: RecipeIngredients[i].IngredientId,
          RecipeId: RecipeId
        })
      );

      promises.push(
        db.RecipeAmount.create({
          Amount: RecipeIngredients[i].AmountForMedium,
          Size: 'md',
          Type: 'smoothie',
          IngredientId: RecipeIngredients[i].IngredientId,
          RecipeId: RecipeId
        })
      );

      promises.push(
        db.RecipeAmount.create({
          Amount: RecipeIngredients[i].AmountForLarge,
          Size: 'lg',
          Type: 'smoothie',
          IngredientId: RecipeIngredients[i].IngredientId,
          RecipeId: RecipeId
        })
      );
    }

    sequelize.Promise.all(promises).then(function () {
      //this does get logged out in the backend console
      console.log('DONE ADDING');
    });

  });
};

【问题讨论】:

  • 您确定您的后端已正确实施,在 POST 请求返回响应之前,配方数据已插入您的数据库等?
  • @DacreDenny 据我所知,所有内容都已正确发布。所有记录都在数据库中,当我刷新页面时,状态也会正确更新。但是,既然你提出来了,我将为我的 addRecipe 控制器添加代码
  • 您是否有任何其他类似的控制器可以按预期运行?看起来您的请求处理程序触发了一些异步函数并立即返回(即:请求将在异步函数完成之前完成)
  • @GeorgeChanturidze 请查看更新后的答案 - 这能解决您的问题吗?
  • 你在哪里发送addRecipe的回复?

标签: javascript reactjs promise async-await axios


【解决方案1】:

我认为解决方案是通过确保调用 res 回调来调整您的 addRecipe 控制器。看到您的“DONE ADDING”消息已记录,我们可以调用res 回调,如下所示:

sequelize.Promise.all(promises).then(function () {
      //this does get logged out in the backend console
      console.log('DONE ADDING');

    res.send(); // <-- call the response callback to send a response back 
           // to client only after DB has been updated
});

这应该确保您在客户端的 axio 发布仅在新数据进入数据库后完成。反过来,这应该会导致对 API.getRecipes() 的调用仅在数据库更新后才被调用 - 然后一切都应该按预期工作

【讨论】:

  • 你怎么在后台调用exports.addRecipe?
  • router.post('/recipes/new', upload.single('selectedFile'), Recipes_controllers.addRecipe); 注意,上传部分是针对我有的文件上传功能的。
  • 好的 - 你为你的后端使用的框架是什么?应该有一种方法来支持后端路由中的异步操作,以便您可以确保数据库在返回结果之前已完成插入。这将是保证您的代码正常运行的关键。
  • 我只是通过 Sequelize ORM 使用 Node 和 Express 服务器,MySQL db。我对“成分”有类似的插入操作,效果很好。在这里,我认为配方数据在发布之前需要更长的时间来处理,所以它只是出错了。我尝试在 getRecipes 之前设置超时,它就像一个 hack。只是想要一个正确的方法:)
  • 太好了-我上面的回答是基于您以这种方式使用快速路由expressjs.com/en/guide/routing.html的假设-换句话说,req 和 res 都传递给了您的路由处理程序(即addRecipe),这样您就可以保证在将响应发送回客户端之前将数据插入到您的数据库中
猜你喜欢
  • 2018-09-19
  • 2019-09-15
  • 2018-05-28
  • 2019-12-03
  • 1970-01-01
  • 1970-01-01
  • 2017-04-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多