Load data asynchron in a JS object [duplicate] - javascript

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
I'm currently writing a JS class for my webshop application to access product information which is stored on the server. The information should be loaded asynchronously. For this I use dojo.xhrPost(). I want to rewrite a function for this class, called getProductName(productId:int):String which returns the product name for a given product id. The function uses intern dojo.xhrPost(). But whould should I return the loaded product name due to the fact that I have to pass new function to load and error in dojo.xhrPost()?
Usage of this function: Other JS functions call this to load the product name to update the cart webpage without reloading the whole page. The data returned is in JSON format due to the fact that some additional information is transferred for error handling (the client function has to know if any error occurred on server-side or not).
The code for the function getProductName(productId:int):
function getProductName(productId) {
dojo.xhrPost({
url: '/shop/dataProduct.php',
handleAs: 'json',
content: {productId:productId},
load: function(response, ioArgs) {
if (!response.error) {
// here I would like to return response.data to the caller of myObj.getProductName(productId)
} else {
// here I would like to return "error" to the caller of myObj.getProductName(productId)
}
return response;
},
error: function(response, ioArgs) {
// here I would like to return "error" to the caller of myObj.getProductName(productId)
return response;
}
});
}
The usage:
var productName = myObj.getProductName(5);

The problem with the following line of code is that it is assuming the the retrieval of the product name is synchronous. But you are making an ajax call to get the name and therefore the code is asynchronous.
var productName = myObj.getProductName(5);
You need to use dojo/Deferred to handle the asynchronous call.
function getProductName(productId) {
var d = new dojo.Deferred();
dojo.xhrPost({
url: '/shop/dataProduct.php',
handleAs: 'json',
content: {productId:productId},
load: function(response, ioArgs) {
if (!response.error) {
var productName = ???;
d.resolve(productName);
} else {
d.reject(response.error);
}
},
error: function(err) {
d.reject(err);
}
});
return d;
}
Usage:
getProductName(1).then(
function(productName) {
// do something with product name
}, function(error) {
// handle error
});
http://dojotoolkit.org/reference-guide/1.8/dojo/Deferred.html

Related

Why ajax call send null to servlet? [duplicate]

This question already has answers here:
How should I use servlets and Ajax?
(7 answers)
HTTP request parameters are not available by request.getAttribute()
(1 answer)
Closed 3 years ago.
I'm trying to send the username to the servlet through an ajax call to check its availability, but the servlet show a null pointer exception.
I've also tried with the XMLHttpRequest instead of $.ajax.
This is my Javascript file:
$(document).ready(function() {
$("#reg-form").submit(function() {
var res = true;
if (!testUser()) {
res = false;
$("#erruser").css("display", "block");
$("#username").addClass("errclass");
} else {
$("#erruser").css("display", "none");
$("#username").removeClass("errclass");
}
return res;
});
});
function testUser() {
var el = $("#username").val();
var b = false;
$.ajax({
type: "POST",
url: "CheckUserServlet",
data: { user: el },
dataType: "json",
success: function(bool) {
alert(bool);
if (bool == "si") b = true;
},
error: function() {
alert("errore");
}
});
return b;
}
This is my servlet doPost method:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username=request.getAttribute("user").toString();
System.out.println("username servlet= "+username);
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
if (!ud.doRetrieveByUser(username)) {
response.getWriter().write("si");
return;
}
response.getWriter().write("no");
return;
}
Thanks!
CLIENT SIDE
Your test user function will always return false regardless of if the server is operating correctly because $.ajax() is an async function. There are a few ways around this. In your case, without knowing much more about what you are building, I would suggest removing the return value from your test user function, and moving your logic into the success/failure areas in the ajax callback. This way, the ajax call just does it's thing and lets the success function modify your page however you want.
function testUser() {
var el = $("#username").val();
$.ajax({
type: "POST",
url: "CheckUserServlet",
data: { user: el },
dataType: "json",
success: function(bool) {
alert(bool);
// put logic here
if (bool === "si") {
$("#erruser").css("display", "block");
$("#username").addClass("errclass");
} else {
$("#erruser").css("display", "none");
$("#username").removeClass("errclass");
}
},
error: function() {
alert("errore");
}
});
}
I would also suggest setting up the initial state of your page so that while this request is happening the user is shown something that makes sense. Answer the following question: "what do I show my users when the page does not know yet if it is a test user" and then set the initial state of the page accordingly
SERVER SIDE
I've always found interacting with java & JSON data a bit clunky, and your issue seems like something I've grappled with in the past.
Your question is "why is ajax sending null to the server". It may seem like that but what is really happening is that your server doesn't understand how to interpret the data it is getting. Take a look at this question about getting a JSON payload.. You need to tell your server how to parse the data coming from the client. If you were to inspect the data being sent, I would expect it looks something like this {"user":"blablabla"}.
If you have a class definition already, use that. For this I am using something that looks like this:
public class UserRequest {
String user;
}
// get the body as a string. Requires https://commons.apache.org/proper/commons-io/
String body = IOUtils.toString(request.getReader())
// parse the json with gson. Requires https://github.com/google/gson
Gson g = new Gson();
User u = g.fromJson(body, UserRequest.class);
String username = u.user;

Sometimes data does not populate from a database [duplicate]

This question already has answers here:
AngularJS : returning data from service to controller
(2 answers)
Why are Callbacks from Promise `.then` Methods an Anti-Pattern
(2 answers)
Why are AngularJS $http success/error methods deprecated? Removed from v1.6?
(2 answers)
Closed 4 years ago.
About 1 in every 10 times I refresh my project, the data from my database is not retrieved and I have to refresh the page again to get it. I tried adding a 101ms timeout onto the function which retrieves the data, and this worked- but also removed a lot of other functionality of the site.
The problem is that sometimes the page loads before the data is retrieved.
Is there a better way to solve this than using a timeout? My code for the POST is below:
get_data: function (kpi, date_from, date_to, callback) {
var config = {
method: 'POST',
url: '/getData',
data: {
kpi: kpi,
date_from: date_from,
date_to: date_to
}
};
$http(config)
.success(function (data) {
callback(data);
})
.error(function (data, status, headers, config) {
console.log(data, status, headers, config);
});
}
And then where this method is called (currently with the timeout, which is breaking other site functionality):
$scope.update_all_data = $timeout(function(){
$scope.show_loading = true;
var date_from = findDateUnix($scope.myDateFrom, $scope.availableDates);
var date_to = findDateUnix($scope.myDateTo, $scope.availableDates);
UpdateSvc.get_data($scope.kpi_selected, date_from, date_to, function(res){
raw_data = [];
if(res.raw_data != null) {
if(res.raw_data.length > 0){
raw_data = res.raw_data;
skey_data = [];
if(res.skey_data != null) {
skey_data = res.skey_data;
}
var num = $scope.show_tab.indexOf(true);
$scope.filtering = generateCategories();
$timeout(function(){
$scope.display_nodata = false;
resizeObjects();
$('.md-datepicker-input').prop('disabled', true);
//Take out loading
$scope.show_loading = false;
}, 100);
}else{
$scope.display_nodata = true;
$timeout(function(){ $scope.show_loading = false;}, 100);
}
}else{
$scope.display_nodata = true;
$timeout(function(){ $scope.show_loading = false;}, 100);
}
});
}, 101);
The problem is that sometimes the page loads before the data is retrieved.
I'm not sure what you mean by this. In an AngularJS application, the entire page must be loaded before AngularJS even begins to work. So your data (retreived with $http) will ALWAYS be loaded after the page loads, unless it is injected server-side.
I don't think you are having any issues retrieving the data from $http. You can easily confirm this by eliminating or commenting out all the code that does not deal directly with data retrieval. I would also strongly recommend the following changes:
First, using callbacks with $http is an antipattern: Why are Callbacks from Promise `.then` Methods an Anti-Pattern
(Note: newer versions of AngularJS use then/catch instead of success/error)
You should, instead use the built-in promise system. Calls to $http return a promise object that can be used directly like so:
get_data: function (kpi, date_from, date_to) {
var config = {
method: 'POST',
url: '/getData',
data: {
kpi: kpi,
date_from: date_from,
date_to: date_to
}
};
// return the $http call
return $http(config)
.error(function (data, status, headers, config) {
console.log(data, status, headers, config);
});
}
There is not really any reason to call $timeout in update_all_data function. You are adding 101 seconds AFTER your $http call has already returned. All that does is delay the display of the data further. Here, we are also calling the success function on the promise returned from the $http call in the service:
$scope.update_all_data = function(){
var date_from = findDateUnix($scope.myDateFrom, $scope.availableDates);
var date_to = findDateUnix($scope.myDateTo, $scope.availableDates);
UpdateSvc.get_data($scope.kpi_selected, date_from, date_to).success(function(data) {
console.log(data);
});
});
If this works and your data is logged 10/10 times then the issue is not with data retreival, it is with the rest of the code in your update_all_data function.

How to return data to variable after ajax call success [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
I have a PHP file returning data in required array format to my FlotChart, it's working.
Now I'm trying to get this result in my script using ajax, however I cannot see result on global variable, as described below:
myJS.js
var EcomDashboard = function() {
return {
init: function() {
var dataEarnings = NULL;
$.ajax({
url:"operation.php",
dataType: "text",
success:function(data) {
alert(data); //show my array [ [1, 20],[2,30],[3,14] ]
dataEarnings = data;
}
});
alert(dataEarnings); //showing "NULL" but I need [ [1, 20],[2,30],[3,14] ]
...
What is the correct way to assign to my variable date Earnings the array [[1, 20], [2.30], [3.14]]?
Javascript is an async language, it means it won't wait the http request to finish to execute the next line. you will have to assign the variable inside the success block.
the alert shows null is becauseit got executed before the $.ajax http request line finishes.
may be you can do this using a callback:
dataAccess.js
var ecomDashboard = function() {
init: function(callback) {
var dataEarnings = NULL;
$.ajax({
url:"operation.php",
dataType: "text",
success:function(data) {
callback(data);
}
});
}
}
controller.js
ecomDashboard.init(function(data){
// data contains the array result
// do your stuff
})
event better:
since jquery 1.5 there is incorporated promise interface, and .success is going to be deprecated. edited: thanks to Kevin B
so with promise:
dataAccess.js
var ecomDashboard = function() {
init: function(callback) {
var dataEarnings = NULL;
return $.ajax({
url:"operation.php",
dataType: "text"
});
}
}
controller.js
ecomDashboard.init().done(function(data){
//do your stuff
alert(data);
}).fail(function(error){
//do stuff when error
});
$.ajax({
url:"operation.php",
dataType: "text",
success:function(data) {
doSomthingOnComplete(data);
}
});
function doSomthingOnComplete(data)
{
// do here your work
}
This is occurring because that alert(dataEarnings) is executing before your ajax request resolves. The first letter in the AJAX acronym is Asynchronous. So, ultimately your data is being set properly you are just trying to access it before the asynchronous call completes.

JS Array values become undefined [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
I have a function that pull information from an XML file located on the system. IT will then pull the values located in that file and put them into an array. Once the function is called the values enter the array, but then onnce the function ends the values go away.
function getXML(location,day){
$(document).ready(function () {
$.ajax({
type:'post', //just for ECHO
dataType: "xml", // type of file you are trying to read
crossDomain:true,
url: './../CurrentFiles/'+ location +'.xml', // name of file you want to parse
success: function (xmldata){
if(array[0] == null){
$(xmldata).find('dgauges').children().each(function(){
array.push($(this).text());
});
}
}, // name of the function to call upon success
error: function(xhr, status, error) {
console.log(error);
console.log(status);
}
});
});
return array[day];
}
From what I researched it could be a problem with async, but I do not understand entirely what that is.
Also I am very new to jquery so if there is any thing that seems out of place that's why.
THis is what my plan is for this function
I have an XML file formatted like
<dgages><d>26.850</d><d-1>7.70</d-1><d-2>2.00</d-2><d-3>27.90</d-3></dgages>
I am trying to pull all of those values in an array so I can do some calculations on them.
Get the XML Document
find all the children of dgage
put each of the children into the array
4 once the array is filled return the associated day.
Try making a synchronous call instead. AJAX calls are async by default, which means that code will jump to the next line before waiting for the result of the previous line. You can enforce the result by telling the AJAX call to do it synchoronously:
function getXML(location, day) {
var array = [];
$.ajax({
type: 'post', //just for ECHO
dataType: "xml", // type of file you are trying to read
crossDomain: true,
async: false, // Wait until AJAX call is completed
url: './../CurrentFiles/' + location + '.xml', // name of file you want to parse
success: function(xmldata) {
if (array[0] == null) {
$(xmldata).find('dgauges').children().each(function() {
array.push($(this).text());
});
}
}, // name of the function to call upon success
error: function(xhr, status, error) {
console.log(error);
console.log(status);
}
});
return array[day];
}

Displaying json returns undefined [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
I have a nested data structure / JSON, how can I access a specific value?
Basically I have a returned json object like this:
"products":[
{
"id": "21102165",
"name": "Eliza J (3/4 sleeve ruched waist dress)",
}]
My method to display it:
function getCart(){
var json = $.getJSON('https://'+storedomain+'/cart?'+fcc.session_get()+'&output=json&callback=?');
alert(json['name']);
}
However the alert displays "undefined". Where I'm I doing wrong here?
Thanks
$.getJSON return $.Deferred object and not a result
function getCart(){
$.getJSON('https://'+storedomain+'/cart?'+fcc.session_get()+'&output=json&callback=?', function(data) {
console.log(data.products[0].name);
});
}
you can do:
function getCart(){
return $.getJSON('https://'+storedomain+'/cart?'+fcc.session_get()+'&output=json&callback=?');
}
$.when(getCart()).then(function(data) {
console.log(data.products[0].name);
});
Use the success callback.
var jqxhr = $.getJSON("example.json", function(data, textStatus, jqXHR) {
alert("success");
})
.success(function(data, textStatus, jqXHR) { alert("second success"); })
.error(function() { alert("error"); })
.complete(function() { alert("complete"); });
See the API documentation for getJSON.
Your method should be:
function getCart(callback) {
var url = 'https://'+storedomain + '/cart?'+fcc.session_get()+'&output=json&callback=?';
$.getJSON(url, callback);
}
// Usage
getCart(function(data) {
console.log(data.products); // array of car objects
});
Or you can use deffered object as explained in salexch answer.
You should become familiar with asynchronous nature of AJAX requests and with callback functions.

Categories

Resources