Basic jquery deferred usage with ajax - javascript

I am trying to rewrite code from How to capture asynchronous ajax response into a variable? to use jquery deferred functions. I started with :
var html ="";
$.ajax({
type:"POST",
url: "Ajax/getHtml",
data: { u : contents },
dataType: 'html',
success: function(data) {
html = data;
},
error: function(jqXHR, textStatus, errorThrown) {
console.log('error');
console.log(jqXHR,textStatus, errorThrown);
}
});
console.log('html', html);
I am trying to turn this into a deferred function which can be resolved when the requested html page is returned. I have been reading http://learn.jquery.com/code-organization/deferreds/examples/ and http://jqfundamentals.com/chapter/ajax-deferreds to do this. So far I've come up with :
var html_response = new $.Deferred(url){
$.ajax({
type:"POST",
url: "Ajax/getHtml",
data: { u : url},
dataType: 'html',
success: html_response.resolve,
error: html_response.reject
});
};
This would be used as part of :
html_response().done{
console.log('html', html);
}
What I am trying to do is when the get_html function returns html sucessfully (i.e get_html is resolved )grab the html and send it to the console. I'm having trouble figuring out how to put the pieces together here. Could someone advise me please.

What you are doing has the right concept.
If I understand correctly, you are trying to do some "true asynchronous" ajax, unlike your last post.
The one thing you are doing incorrectly is resolving your deferred jQuery variable.
The correct code should look like this:
var html_response = $.Deferred(); // no need for new
function get_html(url){
$.ajax({
type:"POST",
url: "Ajax/getHtml",
data: { u : url},
dataType: 'html',
success:function(data) {
html_response.resolve(data); //resolve is a fn
},
error: function(x, status, err) {
html_response.reject(err); //reject is a fn
}
});
};
}
get_html(inserturlhere);
html_response.done(function(html){ // handle success
console.log('html: ' + html);
})
.fail(function(error) { // handle failure
console.log(error);
});
However, ajax comes explicitly with a defer already, so be sure to check that out first. http://api.jquery.com/jquery.ajax/

This works because $.ajax returns it's own promise (like animations), negating the need to create your own deferred object.
function html_response(url){
return $.ajax({
//ajax stuff
});
}
html_response(url).done(function(data){
console.log(data);
});

You don't need a full Deferred here. You just need a Promise, whose interface is a subset of that of a Deferred (see the doc on Deferred for more info). The promise has a method .done() that lets you provide a callback to be executed when the asynchronous process ends successfully.
The $.ajax() method returns a jqXHR object which conveniently implements the Promise interface:
The jqXHR objects returned by $.ajax() as of jQuery 1.5 implement the
Promise interface, giving them all the properties, methods, and
behavior of a Promise
So when you call $.ajax, you already have a promise. Just do:
$.ajax({
...
}).done(function(data){
console.log(data);
});
Alternatively, if you really want to deal with a full Deferred object, you could do:
var defr = $.Deferred();
defr.done(function(data){
console.log(data);
});
$.ajax({
...
,sucCess : function(data){
defr.resolve(data);
}
});

Related

generalizing ajax call into function

I'm trying to attempt to generalize my ajax calls into a function as follows. I have not done this before and am not sure sure if I'm doing it correctly.
<script>
$(document).ready(function(){
var reg_no=$("#reg_no").val();
reg_no=reg_no.trim();
if(reg_no!==""){
//populate fields
data={reg_no:reg_no,func:"getSupplierDetails"};
success_function="updateFormFields";
ajax_call(data,success_function);
}
});
function ajax_call(data,success_function){
$.ajax({
type:"POST",
url:"../control/supplier-c.php",
dataType:"json",
data:data,
success:function(data){
success_function(data); //variable function works??
}
});
}
function updateFormFields(data){
//some code here to handle data array
}
</script>
What I'm trying to do here is avoid rewriting the whole ajax code by passing the data array and the function to be executed on success. What I'm not sure is the use of variable functions as i have done.
A note to be made is that the whole thing works for an ajax call if updateFormFields() code was moved into the success handler in the ajax call and the ajax_call() was not defined as a seperate function but implemented right after the comment "populate fields". I just have no experience in trying it this way and I need to know if this is possible or not.
Thank You
In Javascript, functions are first class objects, meaning you can pass them around as parameters.
function json_post(url, data, success_function, error_function) {
$.ajax({
type:"POST",
url:url,
dataType:"json",
data:data
}).then(success_function, error_function);
}
Then you can call it as
json_post("../control/supplier-c.php", { data: "data" }, function (res) {
console.log('Ajax req successful');
console.log(res);
}, function (res) {
console.log('Error in ajax req');
console.log(res);
});
In your case, you can do:
ajax_call(data, updateFormFields);
and it should work as expected.
There's no need to wrap the success function, you can just apply apply it directly.
function ajax_call(data, success_function) {
$.ajax({
...
success: success_function
});
}
An even better idea is to avoid the legacy success and error callbacks and instead return the jQuery promise. You can use standard promise methods .then() and `.
function ajax_call(data) {
return $.ajax({
...
});
}
ajax_call()
.then(function(data) {
// this runs if it succeeds
})
.fail(function(err) {
// this runs if it failed
});
Promises have a huge benefit to being chain-able, making the code flatter, avoiding the nest of "christmas tree callbacks".
I would recommend checking success_function as well as failure_function to handle server response (XHR) errors also.
function success_function(){
//code to handle success callback
}
function error_function(){
//code to handle failure callback
}
function ajax_call(data, success_function, error_function) {
if (typeof success_function === 'function' && typeof error_function === 'function') {
$.ajax({
type: "POST",
url: "../control/supplier-c.php",
dataType: "json",
data: data,
}).then(success_function).fail(error_function);
}
}

JS — Trying to return AJAX data

I've been struggling with getting the data out of an AJAX call using jQuery. I'm using RequireJS so my JavaScript can be more maintainable/modular. I've only been using RequireJS for a few days, so I may or may not be doing this right. Just looking for a way to keep my JS modular and clean.
Here is what I have so far. I know for a fact that it's getting the correct data because if I console.log(data[Math.floor(Math.random()*data.length)]), the data is there. The JSON file is long so I won't show you that, just take my word for it — it works.
var maze;
define(["jquery"], function($){
$.ajax("js/mazes.json", {
dataType: "json",
type: "get",
success: function(data){
var maze = data[Math.floor(Math.random()*data.length)];
}
});
return {
randomMaze: maze
};
});
I also tried this (declaring maze within anonymous function)
define(["jquery"], function($){
var maze;
$.ajax("js/mazes.json", {
dataType: "json",
type: "get",
success: function(data){
var maze = data[Math.floor(Math.random()*data.length)];
}
});
return {
randomMaze: maze
};
});
I don't know what I'm doing wrong. Just trying to return data[Math.floor(Math.random()*data.length)]
jQuery.ajax() success returns results asynchronously , maze may not be defined when called synchronously outside of success at
return {
randomMaze: maze
};
Try returning jQuery promise object $.ajax() from function , returning object within asynchronous success callback
// return jQuery promise object
return $.ajax("js/mazes.json", {
dataType: "json",
type: "get",
success: function(data){
// return object as jQuery promise value
return {
randomMaze: data[Math.floor(Math.random()*data.length)];
}
}
});
See also How do I return the response from an asynchronous call?

Calling a method after two other methods have been completed

I am looking for the best standard javascript way of monitoring when a method is completed.
I have a method used for ajax calls like this:
function rdRelatedJobs(param1,param2,param3) {
var completeURL = param1 + param2 + param3;
$.ajax({
type: "GET",
url:completeURL,
dataType: "xml",
success: function(xml){
// We parse the XML here
};
},
error: function() {
console.log("An error occurred while processing XML file.");
}
});
} // end function rdRelatedJobs
This function is called twice, queued immediately after each other. What I need to know is how to call another method once the second call to this method is complete.
Note it does not matter if the ajax request is success or failure in this case. I just need to know how to call the method once the method above is run twice.
There's a jQuery-specific answer, and a general answer.
The jQuery-specific answer is to return the result of the ajax call, which is a jqXHR object:
function rdRelatedJobs(param1,param2,param3) {
var completeURL = param1 + param2 + param3;
return $.ajax({
type: "GET",
url:completeURL,
dataType: "xml",
success: function(xml){
// We parse the XML here
},
error: function() {
console.log("An error occurred while processing XML file.");
}
});
} // end function rdRelatedJobs
...and when you're calling rdRelatedJobs, use $.when:
$.when(
rdRelatedJobs(/*...args for first call...*/),
rdRelatedJobs(/*...args for second call...*/)
).then(function() {
// both are done now
});
That works because jqXHR objects implement the jQuery Promise API, and $.when will call your callback when all of the promises you give it have been fulfilled.
The generic answer would be to use a promise library that does something similar.
Or another generic answer would be to have rdRelatedJobs call a callback when it's done, and to maintain a counter:
function rdRelatedJobs(param1,param2,param3,done) {
var completeURL = param1 + param2 + param3;
return $.ajax({
type: "GET",
url:completeURL,
dataType: "xml",
success: function(xml){
// We parse the XML here
done(xml);
},
error: function() {
console.log("An error occurred while processing XML file.");
done(null);
}
});
} // end function rdRelatedJobs
...and then:
var counter = 0;
function done(result) {
if (--counter === 0) {
// Both are done
}
}
rdRelatedJobs(/*...args for first call...*/, done);
++counter;
rdRelatedJobs(/*...args for second call...*/, done);
++counter;
That looks like a race condition, but it isn't, because there is only one main UI JavaScript thread in browsers.
outside the function you can have a `var counter`
and then inside:
$.ajax({
type: "GET",
url:completeURL,
dataType: "xml",
success: function(xml){
// We parse the XML here
counter++;
if(counter==2) bla bla
};
},
error: function() {
console.log("An error occurred while processing XML file.");
counter++;
if(counter==2) bla bla
}
});
function rdRelatedJobs(param1,param2,param3) {
var completeURL = param1 + param2 + param3;
// return an ajax promise from this function
return $.ajax({
type: "GET",
url:completeURL,
dataType: "xml",
success: function (xml) {
// We parse the XML here
},
error: function () {
console.log("An error occurred while processing XML file.");
}
});
}
// compile the promises by passing them into an array
function getPromises() {
var promises = [];
promises.push(rdRelatedJobs(1, 2, 3));
promises.push(rdRelatedJobs(3, 4, 5));
return promises;
}
// use $.when by passing in the promise array using the apply method
$.when.apply(null, getPromises()).then(function () {
// do a thing
});
You could use a library called Q and do an 'all' and use a 'then' with a success and failure callback
https://github.com/kriskowal/q
e.g:
Q.all([rdRelatedJobs(x,y,z), rdRelatedJobs(a,b,c)]).then(function () {
console.log("Data saved!");
});
Very similar to the jquery $.when the 'then' will only get called when both ajax requests have finished. You would have to alter the rdRelatedJobs to do a return just before the $.ajax so that the promise is returned from the function.

function and defered jquery

Hello i'm very confused on this argument: I know that in javascript function executes in an
asyncronous way sometimes and here is my problem. i have a function called
function createPopupHour()
this function creates an html select element and it doesn't return nothing. I call this function in a $.AJAX request in the success part of the request.
$.ajax({
url:"responseregistrodocente.php",
data:{
operazione:'caricaAssenza',
idAssenza:id_array[3],
codiceFiscale: id_array[0],
data:id_array[1],
tipo:id_array[2]
},
type:"POST",
dataType:"json",
success: function (jsonObject) {
createPopupHourSelect()
//other code
});
},
error: function(error){
//XMLREQQUESTOBJECT
alert(error.responseText);
location.reload();
},
cache:false,
ifModified:false
});
the problem is that when i call the function the other code doesn't attent that my function end. i know that in jquery there is the "deferred Object",maybe i need that my function create a deferred object, and return it to the code. but how is the sintax:? or is there another more easy and dry solution???
is correct something like this?
function createPopupHour select(){ //staff to do
return $.deferred();//it's in pending state
}
and $.ajax
$.ajax({
url:"responseregistrodocente.php",
data:{
operazione:'caricaAssenza',
idAssenza:id_array[3],
codiceFiscale: id_array[0],
data:id_array[1],
tipo:id_array[2]
},
type:"POST",
dataType:"json",
success: function (jsonObject) {
var defered=createPopupHourSelect()
defered.then(function{//other code])
defered.resolve();
});
},
error: function(error){
//XMLREQQUESTOBJECT
alert(error.responseText);
location.reload();
},
cache:false,
ifModified:false
});
Yes, the other code needs to reside in a callback function that will be executed when popup thing is done, just like the popup startup code is executed when the ajax is done. You can either use a primitive callback, or use the more powerful promise pattern.
The syntax for jQuery Deferred objects is
function …() {
var def = $.Deferred();
// start asynchronous task
// when the task is done (in the future), call
def.resolve(…); // optionally with results
// and right now do
return def.promise();
}
Since $.ajax does return a promise as well, you can use chaining via .then (assuming createPopUpHourSelect is in the above pattern):
$.ajax({
url:"responseregistrodocente.php",
data:{…},
type:"POST",
dataType:"json",
cache:false,
ifModified:false
})
.fail(function(error){
alert(error.responseText);
location.reload();
})
.then(createPopupHourSelect) // gets passed the parsed JSON
.then(function(result) { // gets passed the resolve arguments from the popup
// other code
});
If you need the ajax response in the other code as well and don't want to pass it through the popup function, use
.then(function(json) {
return createPopupHourSelect(…)
.then(function(popupResults) {
// other code
});
}) /* returns a promise that resolves with result of other code
.then(…) */

how to use properties and methods withing a JavaScript class to exchange data?

i have small issue with exchanging data in between methods in a JavaScript object (class):
var TEST = (function () {
var TEST = function() {
};
TEST.prototype.get = function() {
$.ajax({
type: "GET",
url: "http://test.com/getall",
dataType: "json",
success: function (data) {
return data; // if i console log this i will get a json obj
}
});
};
TEST.prototype.parse = function(data) {
$.each(this.get(), function(k, v){
console.log(v);
});
};
return TEST;
})();
so i am trying to call one method in the each statement in another method. the issue is that
the response is undefined.
i also tried it like this, but with he same result
var testing = new TEST();
var get = testing.get();
testing.parse(get);
What am i missing? how can i return the data from this.get to be used in this.parse.
thanks
$.ajax() per default is asynchronous. That means, that the execution of your function get() wont wait until the request is finished. Hence you return no value from it, which results in undefined being returned.
In order to have your get() function be able to return a value, you would have to do the request in a synchronous way and set a variable in the outer function (as success itself is just another function, whose return value is not caught):
TEST.prototype.get = function() {
var result;
$.ajax({
type: "GET",
url: "http://test.com/getall",
async: false, // this is the important part!
dataType: "json",
success: function (data) {
result = data;
}
});
return result;
};
EDIT
As mentioned by #pebbl, this will halt the execution of all your scripts, until the request is done. Hence your whole page will be blocked for the time being.
The general approach is to use callbacks in such cases, which will be executed once the requests finished. So in your case something like this:
TEST.prototype.get = function( cb ) {
$.ajax({
type: "GET",
url: "http://test.com/getall",
dataType: "json",
success: function (data) {
cb( data );
}
});
};
with later on calling like this:
var testing = new TEST();
testing.get( function( data ) {
testing.parse( data );
});
You can't construct your function this way as you are relying on an asyncronous call, which will return it's result outside of the normal execution flow. The only way you can actually receive the result of your .get function is to use a callback.
Put simply your value isn't being returned from the .get function, it's being returned from the callback you are passing into jQuery's .ajax method.
You'd be far better off redesigning your code so as to still support the asyncronous call -- rather than disabling async.
A rough idea is to change your parse function like so:
TEST.prototype.parse = function(data) {
this.get(function(result){
$.each(result, function(k, v){
console.log(v);
});
});
};
And to change your get function accordingly:
TEST.prototype.get = function(callback) {
$.ajax({
type: "GET",
url: "http://test.com/getall",
dataType: "json",
success: callback
});
};
The above is just a quick example, you'd be wise reading up on the following jQuery topics:
http://api.jquery.com/promise/
http://api.jquery.com/category/deferred-object/
If you design your code around the promise pattern you'll find it complicated at first, but it gives you a lot of power in your code -- and gets around the whole callback stacking madness you can end up with when dealing in ajax calls.
Whilst it's not entirely clear from the jQuery.ajax documentation, this function returns a jqXHR object which implements the promise interface. So this means you can use the promise methods done, always and fail.
http://api.jquery.com/jQuery.ajax/

Categories

Resources