如何在页面加载时使用Javascript创建成功的Ajax请求

时间:2016-12-11 17:44:47

标签: javascript ajax node.js express

我正在开发购物车应用程序。用户将向他们的购物车添加商品'它存储在本地存储中。当用户导航到他们将项目添加到购物车的其他页面时,页面需要填充他们添加到购物车的项目(本地存储)。我正在使用把手为我的页面构建模板,NodeJS / ExpressJS用于创建路由并为get / post请求填充页面,以及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&#34; viewCartTable&#34;在那里执行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匹配的产品及其信息。

所以这个当前的设置第一次通过。对页面的初始访问将打印产品的数据在本地存储中,并发送&#34;成功&#34;到了前端。但是在它们被设置之后立即跟随Cant设置标题之后。我相信这是因为当我找到&#34; viewCartTable&#34;我正在发送一个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' } ]

在我构建这样的表的所有其他实例中,我已经能够调用结果[0] .productId来获取结果的特定productId。在这里,它返回一个未定义的。所有其他尝试也返回未定义。任何想法如何轻松迭代这个数据集的每一部分?在我无法弄清楚这一点的想法中,我觉得我对此感到愚蠢:(

1 个答案:

答案 0 :(得分: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个。这意味着你多次调用它。这意味着您正在尝试为此请求发送多个响应,并触发您看到的错误。这是错误的服务器代码。您只需为任何给定的请求发送一个响应。

在我建议哪种代码最能解决这个问题之前,我必须先了解所需的单一响应。如果您打算执行多个这样的异步操作,并且想知道它们何时完成,那么您必须编写代码来跟踪它们并在完成所有操作后收到通知,然后发送一个且只发送一个响应。

这可以通过计数器和一些代码手动完成,以递增和检查计数器,或者可以通过切换到使用promises来跟踪异步操作并使用Promise.all()以更加管理的方式完成完成所有异步操作后通知您。

如果此功能中有多个键,发送所需的单个响应是什么?

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

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);       
      });
    },