My original task is the following:
Execute jQuery.ajax()
On success, do some extra checks on the data returned by the server
If these checks fail, return a rejected promise.
After googling and stackoverflowing, the following solution was born:
$.ajax({
type: "POST",
url: "some url",
data: somedata,
error: somefunction
}).then(function (data) {
if (!ajaxSuccess(data, null, null)) {
return new $.Deferred().reject().promise();
}
return data;
});
(Function ajaxSuccess does perform the checks mentioned above in paragraph 2.)
What I dislike about this code is the last line:
return data;
IMHO, it would be much more correct to return the original ajax jqXHR object, since the result of the code will be used by a third-party library js-Grid.com, which expects a jqXHR/promise.
So the questions are:
Is it more correct to return the original ajax jqXHR rather than parsed JSON?
How to return the original jqXHR?
Thanks very much in advance.
opinions are irrelevant - do what you require for your code
jQuery has a very loose interpretation of how Promises work, especially with AJAX family of functions, the callback function passed to .then actually receives THREE arguments
So, you could do:
$.ajax({
type: "POST",
url: "some url",
data: somedata,
error: somefunction
}).then(function (data, textStatus, jqXHR) {
if (!ajaxSuccess(data, null, null)) {
return new $.Deferred().reject().promise();
}
return jqXHR;
});
Related
I have an ajax call that might take a bit to complete. I don't want to use async:false because I want it to stay non blocking code. So I decided to use Q. The problem is I don't understand how ca I extract the json that came back from Q.when($.ajax...). I'm new to Q.
In this example I would like the variable to hold the json that came back from the server:
var res = Q.when($.ajax({
type: "POST",
url: "GetData.asmx/GetMembersList",
contentType: "application/json; charset=utf-8",
dataType: "json"
}));
return res;
With asynchronous calls you can't just assign the result to a variable, because that result won't exist until sometime in the future. Q.when does not return the result, it returns a promise object that will eventually resolve with a result.
If there is only ever one thing you want to do with the JSON you could just inline a .then call to get the result.
Q($.ajax({
type: "POST",
url: "GetData.asmx/GetMembersList",
contentType: "application/json; charset=utf-8",
dataType: "json"
})).then(function (res) {
// res now contains the JSON
});
However the real power of promises comes with the fact that you can pass them around and use them later.
function getMembersList() {
return Q($.ajax({
type: "POST",
url: "GetData.asmx/GetMembersList",
contentType: "application/json; charset=utf-8",
dataType: "json"
}));
}
var membersList = getMembersList();
membersList.then(function (res) {
// once the AJAX call completes this will
// run. Inside this function res contains the JSON
return res; // pass res to the next chained .then()
}).then(function (res) {
// you could chain another then handler here
});
// do some other stuff
membersList.then(function (res) {
// you could also add another then handler later too
// even long after the AJAX request resolved and this
// will be called immediately since the promise has already
// resolved and receive the JSON just like the other
// then handlers.
});
You don't need to use Q if you don't have other reasons for using it, since version 1.5 jQuery returns a deferred object from AJAX calls. A Deferred is similar to a promise. Q does offer more power and jQuery's promises/deferreds don't exactly implement the Promises/A standard, potentially causing problems with error handling. For something simple like an AJAX call jQuery promises are usually good enough if you are already using jQuery anyway.
var membersList = $.ajax({
type: "POST",
url: "GetData.asmx/GetMembersList",
contentType: "application/json; charset=utf-8",
dataType: "json"
});
membersList.then(function (res) {
// res now contains the JSON
});
Here are some examples from the q documentation about using with jQuery ajax.
return Q(jQuery.ajax({
url: "foobar.html",
type: "GET"
})).then(function (data) {
// on success
}, function (xhr) {
// on failure
});
// Similar to jQuery's "complete" callback: return "xhr" regardless of success or failure
return Q.promise(function (resolve) {
jQuery.ajax({
url: "foobar.html",
type: "GET"
}).then(function (data, textStatus, jqXHR) {
delete jqXHR.then; // treat xhr as a non-promise
resolve(jqXHR);
}, function (jqXHR, textStatus, errorThrown) {
delete jqXHR.then; // treat xhr as a non-promise
resolve(jqXHR);
});
});
https://github.com/kriskowal/q/wiki/Coming-from-jQuery
Hope that helps.
I'm trying to a jquery ajax call on jsfiddle but am having an issue:
var ajax1 = function () {
return $.ajax({
type: "post",
url: "/echo/json/",
data: {
name: "thomas!"
},
dataType: 'json'
});
};
var res = ajax1();
console.log(res);
prints an entire deferred object to the console. It includes responseText which I thought perhaps is what I should try to access, but I get undefined.
console.log(res.responseText);
I tried this once before with HTML and everything seemed to work, but the JSON is failing for some reason.
ajax returns a promise object, not the result of the ajax request. You need to register a success callback to get the value returned by the ajax request
It should be
var ajax1 = function () {
return $.ajax({
type: "post",
url: "/echo/json/",
//also the format for json request is as follows
data: {
json: JSON.stringify({
name: "thomas!"
})
},
dataType: 'json'
});
};
var res = ajax1();
res.done(function (data) {
console.log(data)
})
Demo: Fiddle
You are correct, JQuery returns a Deferred object instance.
You should therefore be calling done() on the object to get the data:
var res = ajax1();
res.done(function(data) { console.log(data); });
$.ajax() returns a jqHXR instance (which implements the Deferred pattern). When you return this from the function you are returning the jqHXR object. This implements a done() method which is passed a callback function.
I'm trying to parse data from the server. Though I'm working on a valid JSON, I always get the JSON unexpected character error.
Please consider this code:
var shows = $.parseJSON(fetchData('contentShows', this.id)); // Returns a valid JSON data
$.each(shows, function(index, value) {
console.log(value.id);
});
fetchData = function(dataRequest, id) {
var data = $.ajax({
url: '/shows.php',
type: 'GET',
dataType: 'json',
success: function(data) {
console.log(dataRequest);
console.log(data);
}
});
return data;
}
This is the sample JSON:
[
{"shows":[],"spool":"/home","name":"Test Name","id":2}
]
The problem is that your fetchData function doesn't return the JSON text, it returns a jqXHR object. (And so when you pass that into $.parseJSON, it gets turned into a string like [object Object], which is of course invalid JSON.)
The reason is that you set the data variable to the result of $.ajax call and return it. The return value of $.ajax is a jqXHR object.
But just changing that isn't sufficient, because the call is asynchronous; it completes after the function has already returned.
Your best bet is to modify fetchData to accept a callback, and then use the fetched data within the callback. Something like this:
fetchData = function(dataRequest, id, callback) {
$.ajax({
url: '/shows.php',
type: 'GET',
dataType: 'json',
success: function(data) {
console.log(dataRequest);
console.log(data);
callback(data);
}
});
}
Used like this:
fetchData('contentShows', this.id, function(showData) {
var shows = $.parseJSON(showData);
$.each(shows, function(index, value) {
console.log(value.id);
});
});
I'm trying to add another asynchronous call to the contract of an existing Deferred before its state is set to success. Rather than try and explain this in English, see the following pseudo-code:
$.when(
$.ajax({
url: someUrl,
data: data,
async: true,
success: function (data, textStatus, jqXhr) {
console.log('Call 1 done.')
jqXhr.pipe(
$.ajax({
url: someUrl,
data: data,
async: true,
success: function (data, textStatus, jqXhr) {
console.log('Call 2 done.');
},
})
);
},
}),
$.ajax({
url: someUrl,
data: data,
async: true,
success: function (data, textStatus, jqXhr) {
console.log('Call 3 done.');
},
})
).then(function(){ console.log('All done!'); });
Basically, Call 2 is dependent on the results of Call 1. I want Call 1 and Call 3 to be executed in parallel. Once all 3 calls are complete, I want the All Done code to execute. My understanding is that Deferred.pipe() is supposed to chain another asynchronous call to the given deferred, but in practice, I always get Call 2 completing after All Done.
Does anyone know how to get jQuery's Deferred to do what I want? Hopefully the solution doesn't involve ripping the code apart into chunks any further.
Thanks for any help.
UPDATE: Please see my follow up question.
You have to call .pipe on the deferred object returned by the first $.ajax call, not inside its success callback (this does not have any effect at all):
$.when(
$.ajax({
// ...
}).pipe(function() {
// return a deferred object from .pipe
return $.ajax({
// ...
});
}),
$.ajax({
// ...
})
).done(function(){ console.log('All done!'); });
.pipe returns a new deferred object which only gets resolved once both, the original deferred object and the returned one get resolved.
Here is some code I'd like to execute. I'd like to wait for AJAX response so I can return something from the server. Any way to achieve this?
function functABC(){
$.ajax({
url: 'myPage.php',
data: {id: id},
success: function(data) {
return data;
}
});
//Wait for AJAX (???)
}
var response = functABC();
When using promises they can be used in a promise chain.
async=false will be deprecated so using promises is your best option.
function functABC() {
return new Promise(function(resolve, reject) {
$.ajax({
url: 'myPage.php',
data: {id: id},
success: function(data) {
resolve(data) // Resolve promise and go to then()
},
error: function(err) {
reject(err) // Reject the promise and go to catch()
}
});
});
}
functABC().then(function(data) {
// Run this when your request was successful
console.log(data)
}).catch(function(err) {
// Run this when promise was rejected via reject()
console.log(err)
})
New, using jquery's promise implementation:
function functABC(){
// returns a promise that can be used later.
return $.ajax({
url: 'myPage.php',
data: {id: id}
});
}
functABC().then( response =>
console.log(response);
);
Nice read e.g. here.
This is not "synchronous" really, but I think it achieves what the OP intends.
Old, (jquery's async option has since been deprecated):
All Ajax calls can be done either asynchronously (with a callback function, this would be the function specified after the 'success' key) or synchronously - effectively blocking and waiting for the servers answer.
To get a synchronous execution you have to specify
async: false
like described here
Note, however, that in most cases asynchronous execution (via callback on success) is just fine.
The simple answer is to turn off async. But that's the wrong thing to do. The correct answer is to re-think how you write the rest of your code.
Instead of writing this:
function functABC(){
$.ajax({
url: 'myPage.php',
data: {id: id},
success: function(data) {
return data;
}
});
}
function foo () {
var response = functABC();
some_result = bar(response);
// and other stuff and
return some_result;
}
You should write it like this:
function functABC(callback){
$.ajax({
url: 'myPage.php',
data: {id: id},
success: callback
});
}
function foo (callback) {
functABC(function(data){
var response = data;
some_result = bar(response);
// and other stuff and
callback(some_result);
})
}
That is, instead of returning result, pass in code of what needs to be done as callbacks. As I've shown, callbacks can be nested to as many levels as you have function calls.
A quick explanation of why I say it's wrong to turn off async:
Turning off async will freeze the browser while waiting for the ajax call. The user cannot click on anything, cannot scroll and in the worst case, if the user is low on memory, sometimes when the user drags the window off the screen and drags it in again he will see empty spaces because the browser is frozen and cannot redraw. For single threaded browsers like IE7 it's even worse: all websites freeze! Users who experience this may think you site is buggy. If you really don't want to do it asynchronously then just do your processing in the back end and refresh the whole page. It would at least feel not buggy.
nowadays I prefer using async function and await syntax
async function functABC(){
await $.ajax({
url: 'myPage.php',
data: {id: id},
success: function(data) {
return data;
}
});
//Wait for AJAX
}
Try this code. it worked for me.
function getInvoiceID(url, invoiceId) {
return $.ajax({
type: 'POST',
url: url,
data: { invoiceId: invoiceId },
async: false,
});
}
function isInvoiceIdExists(url, invoiceId) {
$.when(getInvoiceID(url, invoiceId)).done(function (data) {
if (!data) {
}
});
}
async: true
When we request for some data to a server, then server will may take some time to return a response. Now During this time browser interpreter resume execution it will not wait for response and continues it's execution. So that response may print second and other code output will be print first. This happens due to async is set to true. Now question arise that what this parameter does. async means asynchronously. This attribute tells to interpreter that do not does execution sequentially.
async: false
Means forcing that complete execution of this call/code first and then go for next. So it is depends on your requirement that how you use this attribute.
Example with async:
function ayncfunction() {
$.ajax({
url: 'abc.php',
data: {id: id},
async: true,
success: function(repsonse) {
return repsonse;
}
});
}
Example without async
function ayncfunction(){
$.ajax({
url: 'abc.php',
data: {
id: id
},
async: false,
success: function(repsonse) {
return repsonse;
}
});
}
use async:false attribute along with url and data. this will help to execute ajax call immediately and u can fetch and use data from server.
function functABC(){
$.ajax({
url: 'myPage.php',
data: {id: id},
async:false
success: function(data) {
return data;
}
});
}
Method 1:
function functABC(){
$.ajax({
url: 'myPage.php',
data: {id: id},
success: function(data) {
return data;
},
complete: function(){
// do the job here
}
});
}
var response = functABC();
Method 2
function functABC(){
$.ajax({
url: 'myPage.php',
data: {id: id},
async: false,
success: function(data) {
return data;
}
});
// do the job here
}