【问题标题】:How to make a successful Ajax request using Javascript on page load如何在页面加载时使用 Javascript 发出成功的 Ajax 请求
【发布时间】:2017-04-26 15:01:50
【问题描述】:

我正在开发一个购物车应用程序。用户将项目添加到存储在本地存储中的“购物车”中。当用户导航到他们将商品添加到购物车的不同页面时,该页面需要填充他们添加到购物车(本地存储)的商品。我使用把手为我的页面构建模板,使用 NodeJS/ExpressJS 为获取/发布请求创建路由和填充页面,并使用 Ajax 向客户端和服务器发送请求以及从客户端和服务器发送请求。

目前,当用户访问查看购物车页面时,我第一次使用它,但是在我收到“错误:发送后无法设置标题”之后立即运行。这也是以一种非常老套/糟糕的方式完成的。

首先,这是我最初获取查看购物车页面的代码:

viewCart: function(req, res){
  if(req.session.success){
    res.render('base', {title: 'View Cart', userNav: true, checkoutNav: true, viewCart: true, cartIcon: true, js:js});
  }else{
      res.render('base', {title: 'View Cart', userNav: true, viewCart: true, cartIcon: true, js:js});
    }
},

这只是渲染页面,其中没有来自本地存储的数据。 这是我要调用的变量的 html,用于填充来自本地存储的数据:

  <div id="viewCartTable"></div>

在我的 Javascript 中,我有这个函数可以查看 id "viewCartTable" 何时存在并执行 ajax 请求:

if(document.getElementById("viewCartTable")){
  var data = localStorage.getItem("Products");
  Ajax.sendRequest("/user/viewCart", function(res){
    responseArr = res.responseText.split('^^^');
    if(responseArr[0] === "error"){
      console.log("error");
      setTimeout(function(){('','#000',false)}, 1500);
    }else if(responseArr[0] === "Success"){
      console.log("Success");
      var tableCart = document.getElementById("viewCartTable");
      tableCart = tableCart.innerHTML = responseArr[1];
    }}, data);
}

这个 Ajax 请求被发送到查看购物车页面的帖子,我相信这可能是问题真正出现的地方。他是帖子:

viewCartPost: function(req, res){
      var data = JSON.parse(req.body.data);
      console.log(data);
      var keys = Object.keys(data);
      //console.log(keys);
      for(var i = 0; i<keys.length; i++){
        var productId = keys[i];
        Product.find({productId: productId}).select({productId : 1, addProductGroupName: 1, productName: 1, productPrice: 1, productDescription: 1, filePath: 1}).exec(function(err, cartProducts){
        if(err){
          console.log(err);
          res.send("error");
        }else{
          res.send("Success^^^"+cartProducts);
        }
        });
        console.log(productId);
      }
    },

这是获取客户端发送的本地存储的信息,并找到与本地存储中存储和发送的productId匹配的产品及其信息。

所以这个当前的设置第一次就可以工作了。初次访问页面,打印本地存储的产品数据,并将“成功”发送到前端。但是在设置了 Cant 设置标题之后立即给出。我相信这是因为当我找到“viewCartTable”的 id 时,我正在发送一个 Ajax 请求。所以必须有更好的方法来触发ajax请求并将数据发送到服务器和从服务器发送回客户端。

有没有更好的方法来发出这个 Ajax 请求以获取所需的数据?到目前为止,加载和加载都失败了。任何帮助表示赞赏。谢谢。

第 2 部分

遍历数据并以表格格式打印。所以在服务器端我正在获取这个函数的结果:

viewCartPost: function(req, res){
      var data = JSON.parse(req.body.data);
      console.log(data);
      var keys = Object.keys(data);
      //console.log(keys);
      var promises = [];
      for(var i = 0; i<keys.length; i++){
        var productId = keys[i];
        promises.push(Product.find({productId: productId}).select({productId : 1, addProductGroupName: 1, productName: 1, productPrice: 1, productDescription: 1, filePath: 1}).exec());
      }
      Promise.all(promises).then(function(results) {
          // you may have to reorganize results to be exactly what you want
          // to return to the client
          var cartTable = viewCartTable(results);
          res.send("Success^^^"+cartTable);
      }).catch(function(err){
          res.sendStatus(500);
      });
    },

并将其发送到正在构建该函数结果表的函数:

function viewCartTable(results){
  console.log(results[0]);
}

现在这个函数只是查看第一个结果。这是 1 个特定产品的整个数据集。看起来像这样:

[ { _id: 583df3eead025434e61a2172,
    filePath: '/public/images/df54528a827f99586135956e45f045fe.jpg',
    addProductGroupName: 'Xbox One',
    productName: 'Far Cry',
    productPrice: 78.34,
    productDescription: 'Its back again. I have never played this game but heard it is pretty good. Wanted to write an extra long description to see if someone really took the time to type such a longer sentence how exactly it would appear on things throughout the application.',
    productId: 'rJUg4uiGl' } ]

在我构建这样一个表的所有其他情况下,我已经能够调用 results[0].productId 来获取结果的特定 productId。在这里,它返回一个未定义的。所有其他尝试也返回未定义。知道如何轻松地遍历该数据集的每一部分吗?我觉得我对此很愚蠢,因为我无法弄清楚这一点:(

【问题讨论】:

  • 您使用的是哪个数据库?这会影响我推荐用于解决此问题的代码。
  • @jfriend00 我在遍历数据时遇到了一些问题。我在我的问题中添加了第 2 部分。任何帮助表示赞赏。
  • 我实际上能够弄清楚这一点。由于创建信息数组的方式,我需要使用 results[0][0].productId 获取特定的数据,以便获取数组数组中第一个结果的 productId。希望那里的术语是正确的。大声笑

标签: javascript ajax node.js express


【解决方案1】:

此服务器代码错误:

viewCartPost: function(req, res){
      var data = JSON.parse(req.body.data);
      console.log(data);
      var keys = Object.keys(data);
      //console.log(keys);
      for(var i = 0; i<keys.length; i++){
        var productId = keys[i];
        Product.find({productId: productId}).select({productId : 1, addProductGroupName: 1, productName: 1, productPrice: 1, productDescription: 1, filePath: 1}).exec(function(err, cartProducts){
        if(err){
          console.log(err);
          res.send("error");
        }else{
          res.send("Success^^^"+cartProducts);
        }
        });
        console.log(productId);
      }
    },

res.send("Success^^^"+cartProducts);for 循环中。这意味着您要多次调用它。这意味着您尝试为此请求发送多个响应,这会触发您看到的错误。这是错误的服务器代码。对于任何给定的请求,您只需发送一个响应。

我必须先了解所需的单一响应是什么,然后才能提出最能解决此问题的代码。如果您打算执行多个诸如此类的异步操作并且想知道它们何时完成,那么您必须编写代码来跟踪它们并在它们全部完成时收到通知,然后发送一个且仅一个响应.

这可以通过计数器和一些代码来手动完成,以增加和检查计数器,也可以通过切换到使用承诺来跟踪您的异步操作并使用Promise.all() 通知您,以更易于管理的方式完成当所有异步操作都完成时。

当您在此函数中有多个键时,希望发送的单个响应是什么?


我自己不太了解 mongoose,但 .exec() 在相当新的 mongoose 版本中返回了一个承诺,因此我们可以使用它来协调多个异步数据库操作,如下所示:

viewCartPost: function(req, res){
      var data = JSON.parse(req.body.data);
      console.log(data);
      var keys = Object.keys(data);
      //console.log(keys);
      var promises = [];
      for(var i = 0; i<keys.length; i++){
        var productId = keys[i];
        promises.push(Product.find({productId: productId}).select({productId : 1, addProductGroupName: 1, productName: 1, productPrice: 1, productDescription: 1, filePath: 1}).exec());
      }
      Promise.all(promises).then(function(results) {
          // you may have to reorganize results to be exactly what you want 
          // to return to the client
          res.json(results);              
      }).catch(function(err){
          console.error("viewCartPost", err);
          res.sendStatus(500);       
      });
    },

【讨论】:

  • 嗯好的。这个想法是让服务器端循环查找不同的密钥。这是添加到本地存储的项目的 productIds。然后我需要它来获取这些多个 productId 并从 mongodb 中找到该特定产品的关联数据。基本上,我需要我的回应是所有产品及其表格格式的数据。单个产品的数据如下所示:{filePath: '/public/images/e6f5cab3de92a9365807cb8301f781b7.jpg', addProductGroupName: 'Xbox One', productName: 'Star Wars', productPrice: 3000, productDescription: 'description', productId: 'BJ_7VOiGg' }
  • @Zgbrell - 我添加了一个解决方案的想法,使用 mongoose promises 来跟踪您的多个操作,收集所有结果并知道它们何时完成。
  • 这似乎工作完美。我真的很不熟悉 mongoose Promises,但看来它确实成功了。它正在发送填充产品表所需的所有数据。
猜你喜欢
  • 2019-07-17
  • 2012-07-29
  • 1970-01-01
  • 2016-04-14
  • 2012-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-01
相关资源
最近更新 更多