如何在页面加载时使用Javascript来实现成功的Ajax请求 [英] How to make a successful Ajax request using Javascript on page load

查看:142
本文介绍了如何在页面加载时使用Javascript来实现成功的Ajax请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在购物车应用程序。用户将添加项目存储到本地存储器中的购物车。当用户导航到不同的页面时,将其添加到购物车的位置,页面需要填充他们添加到购物车(本地存储)的项目。我正在使用句柄为我的页面构建模板,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中,我有这个功能,看到idviewCartTable在那里,并执行ajax请求:

  if(document.getElementById(viewCartTable)){
var data = localStorage.getItem 产品);
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];
}},数据);
}

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

  viewCartPost:function(req,res){
var data = JSON.parse(req .body.data);
console.log(data);
var keys = Object.keys(data);
//console.log(keys); (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, cart产品){
if(err){
console.log(err);
res.send(error);
} else {
res.send (成功^^^+ 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 = []; (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){
//您可能需要重新组织结果才能正确地获得
//返回客户端
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:'它的回来。我从来没有玩过这个游戏,但听说这是非常好的。想要写一个额外的长的描述,看看有没有人真的花时间输入这样一个更长的句子,在整个应用程序中的事情会如何出现。
productId:'rJUg4uiGl'}]

在我建立这样一个表的所有其他实例中,我已经能够调用result [0] .productId来获取具体的productId的结果。在这里,它返回一个未定义的。所有其他尝试也返回了一个未定义的。任何想法如何轻松地遍历每一块这样的数据集?我觉得我在这个想法中很愚蠢,我无法理解:(

解决方案

这个服务器代码是错误的:

  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 ; {
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);
}
});
控制台.log(productId);
}
},

你有code> res.send( 成功^^^ + cartPro管道); 里面循环。这意味着你多次打电话。这意味着您尝试为此请求发送多个响应,并触发您看到的错误。这是服务器代码错误。您只需要为任何给定的请求发送一个响应。



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



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



当您在此功能中有多个按键时,需要单个响应发送什么?






我不知道mongoose mokoose最近版本中的 .exec()返回一个承诺,所以我们可以使用它来协调多个异步数据库操作,如下所示:

  viewCartPost:function(req,res){
var data = JSON.parse(req.body.data);
console.log(data);
var keys = Object.keys(data);
//console.log(keys);
var promises = []; (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){
//您可能需要重新组织结果才能正确地获得
//返回($)
res.json 500);
});
},


I am working on a shopping cart application. The user will add items to their 'cart' which is being stored in local storage. When the user navigates to a different page from where they were adding the items to their cart, the page needs to be populated with the items that they added to their cart(local storage). I am using handlebars to build the templates for my pages, NodeJS/ExpressJS to create routes and populate pages for get/post requests, and Ajax to send requests to and from the client and server.

Currently when the user visits the view cart page I have it working the first time through but, immediately after I get a 'Error: Can't set headers after they are sent.'. This is also being accomplished in quite a hacky/bad way.

To begin, here is my code for the initial get of the view cart page:

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

This is just rendering the page with no data from the local storage in it. Here is the html of the variable I am calling to, to populate with the data from local storage:

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

In my Javascript I have this function that is seeing when the id "viewCartTable" is there and executing an ajax request:

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

This Ajax request is sent to the post for view carts page and I believe this may be where the issue is really unfolding. He is the post:

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

This is getting the information of local storage that was sent from the client side, and finding the products and their information that match the productId that is stored and sent in the local storage.

So this current set up works the first time through. The inital visit to the page prints the data of the products in local storage as well as sends the "Success" to the front-end. But immediately following the Cant set headers after they have been set is being given. I believe that this is because when I find the id of "viewCartTable" I am sending an Ajax request. So there must be a better way to trigger the ajax request and send the data to and from the server and back to the client.

Is there a better method to making this Ajax request to get the needed data? Load and onloads have all failed me in my attempts thus far. Any help is appreciated. Thank you.

Part 2

Iterating through the data and printing it in table format. So on the server side I am taking the results of this function:

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

and sending it to a function that is building a table of the results from this function:

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

Right now this function is just looking at the first result. Which is the entire data set of 1 specific product. Looks like so:

[ { _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' } ]

In all other instances of me building a table like this I have been able to call results[0].productId to get the specific productId of the results. Here, it is returning an undefined. All other attempts have also returned an undefined. Any idea how to easily iterate through each piece of this data set? I feel like I am being stupid about this in the idea that I cannot figure this out :(

解决方案

This server code is wrong:

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

You have res.send("Success^^^"+cartProducts); inside a for loop. That means you're calling it multiple times. That means you're trying to send more than one response for this request and that triggers the error you see. This is faulty server code. You need to only send ONE response for any given request.

I would have to understand what the desired single response is before I could suggest what code would best solve this issue. If you intend to execute multiple asynchronous operations such as this and you want to know when all of them are done, then you have to write code to keep track of them and be notified when they are all done and then send one and only one response.

This can be done manually with a counter and some code to increment and check the counter or it can be done in a more manage way by switching to use promises to keep track of your asynchronous operations and using Promise.all() to notify you when all the asynchronous operations are done.

When you have multiple keys in this function, what is the desired single response to send?


I don't know mongoose too well myself, but .exec() in a fairly recent version of mongoose returns a promise so we can use that to coordinate multiple async database operations like this:

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

这篇关于如何在页面加载时使用Javascript来实现成功的Ajax请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆