Using vktemplate isn't quite working when I try to use jquery deferreds. Since the vktemplate makes an ajax call of its own, the deferred gets resolved before vktemplate completes its work, and its optional callback. How can I set up vk so that the promise doesn't get resolved until after these two things happen?
$(document).on('click', '.ajax', function() {
$.when(ajax1('<p>first</p>'),
ajax2('<p>second</p>'),
ajax3('<p>third</p>'))
.then(function(results1, results2, results3) {
console.log(results1);
$('.document').append(results1);
$('.document').append(results2);
$('.document').append(results3);
alert('all ajax done');
});
});
function ajax1(data) {
$.ajax({
type: 'post',
url: 'templates/test_template.tmpl',
data: "data=" + data,
dataType: 'json',
success: function (returnedData) {
$('#resultsDiv').vkTemplate('templates/test_template.tmpl', returnedData, function () {
//vk callback
//possibly call my resolve here?
});
}
});
}
function ajax2(data){//more of the same}
Since vkTemplate returns nothing you need to manually create a deferred and resolve it in success callback with required data.
function ajax1(data) {
var dfd = $.Deferred();
$.ajax({
type: 'post',
url: 'templates/test_template.tmpl',
data: "data=" + data,
dataType: 'json',
success: function (returnedData) {
$('#resultsDiv').vkTemplate('templates/test_template.tmpl', returnedData, function (el, data, context) {
dfd.resolveWith(context, [$(el)]);
});
}
});
return dfd.promise();
}
Related
I have trouble async disable ajax. I have the following code:
function GetDataFromUninorte() {
link="http://www.uninorte.edu.co/documents/71051/11558879/ExampleData.csv/0e3c22b1-0ec4-490d-86a2-d4bc4f512030";
var result=
$.ajax({
url: 'http://whateverorigin.org/get?url=' + link +"&callback=?" ,
type: 'GET',
async: false,
dataType: 'json',
success: function(response) {
console.log("Inside: " + response);
}
}).responseText;
console.log("Outside: "+result);
return result;
}
And I get the following result:
"Outside" always runs first
As you can see, "Outside" always runs first and the result is undefined and can not process data.
I have already tried
When ... Then
Async = false
passing data as parameters I / O function
and other things, but nothing
:/
... Beforehand thank you very much
(I am not a native english speaker, I apologize if I do not write well)
[Solved]
Maybe is not the best form, but in the "success:" statement I call a function that receive the ajax response and trigger the rest of the process, in this way I not need store the in a variable and the asynchrony not affect me.
Use can use callbacks, you can read more here
function GetDataFromUninorte(successCallback, errorCallback) {
link="http://www.uninorte.edu.co/documents/...";
$.ajax({
url: 'http://whateverorigin.org/get?url=' + link +"&callback=?" ,
type: 'GET',
async: false,
dataType: 'json',
success: successCallback,
error: errorCallback
});
}
function mySuccessCallback(successResponse) {
console.log('callback:success', successResponse);
}
function myErrorCallback(successResponse) {
console.log('callback:success', successResponse);
}
GetDataFromUninorte(mySuccessCallback, myErrorCallback);
Or you can use promises (bad support in IE browsers)
function GetDataFromUninorte() {
return new Promise(function(resolve, reject) {
link="http://www.uninorte.edu.co/documents/...";
$.ajax({
url: 'http://whateverorigin.org/get?url=' + link +"&callback=?" ,
type: 'GET',
async: false,
dataType: 'json',
success: resolve,
error: reject
});
});
}
GetDataFromUninorte()
.then(function(successResponse){
console.log('promise:success', successResponse);
}, function(errorResponse){
console.log('promise:error', errorResponse);
});
AJAX being asynchronous by nature, you need to pass callback, which will be called when the ajax response is received. You may then access responseText from the xhr object.
You can also you jQuery Deferred and promise to get around your problem like below:
function GetDataFromUninorte() {
var defObject = $.Deferred(); // create a deferred object.
link="http://www.uninorte.edu.co/documents/71051/11558879/ExampleData.csv/0e3c22b1-0ec4-490d-86a2-d4bc4f512030";
$.ajax({
url: 'http://whateverorigin.org/get?url=' + link +"&callback=?" ,
type: 'GET',
async: false,
dataType: 'json',
success: function(response) {
console.log("Inside: " + response);
defObject.resolve(response); //resolve promise and pass the response.
}
});
return defObject.promise(); // object returns promise immediately.
}
and then:
var result = GetDataFromUninorte();
$.when(result).done(function(response){
// access responseText here...
console.log(response.responseText);
});
You should avoid making AJAX synchronous by setting async:false as that will block further interactions on the User Interface.
Use this:
function GetDataFromUninorte() {
link="http://www.uninorte.edu.co/documents/71051/11558879/ExampleData.csv/0e3c22b1-0ec4-490d-86a2-d4bc4f512030";
var result=
$.ajax({
url: 'http://whateverorigin.org/get?url=' + link +"&callback=?" ,
type: 'GET',
**timeout: 2000,**
async: false,
dataType: 'json',
success: function(response) {
console.log("Inside: " + response);
}
}).responseText;
console.log("Outside: "+result);
return result;
}
I make 2 ajax calls. Second one should be called only when the first is finished:
var deferred = $.Deferred();
firstAjaxCall();
deferred.done(function () {
secondAjaxCall();
});
function firstAjaxCall() {
$.ajax({
url: '/SomeUrl',
type: 'POST',
success: function () {
deferred.resolve();
}
});
}
function secondAjaxCall() {
$.ajax({
url: '/SomeOtherUrl',
type: 'Get',
});
}
I also tried like this (jQuery deferreds)
$.when(firstAjaxCall()).done(function() {
secondAjaxCall();
});
but no luck.
Still, in the first example, sometimes the second call gets called first, sometimes it doesn't
In the first example the flow is like this:
firstAjaxCall();
secondAjaxCall();
deferred.resolve();
why is second call called first and before deferred.resolve() ?
You have to actually return the Deferred from $.ajax to $.when to make that work
function firstAjaxCall() {
return $.ajax({
url : '/SomeUrl',
type : 'POST'
});
}
function secondAjaxCall(data_from_first) {
return $.ajax({
url : '/SomeOtherUrl',
type : 'Get',
});
}
firstAjaxCall().done(secondAjaxCall);
You can try to call secondAjaxCall() in the success function of the first one
Like this :
function firstAjaxCall() {
return $.ajax({
url: '/SomeUrl',
type: 'POST',
success: secondAjaxCall()
});
}
So say i have multiple ajax requests that are fired at the same time through a parent function. Each ajax function has a seperate individual completion function which are unrelated to each other. If i want a further function to execute upon completion of all ajax functions, but after the completion functions specified in each individual ajax function, how would i go about this?
function ajax1(str) {
return $.ajax({
type: 'get',
data: "q=" + str,
url: 'foo.php',
success: function (result) {
//success!
}
},
complete: function (data) {
function ajaxcomplete1();
},
)
};
function ajax2(str) {
return $.ajax({
type: 'get',
data: "q=" + str,
url: 'foo.php',
success: function (result) {
//success!
}
},
complete: function (data) {
function ajaxcomplete2();
},
)
};
function ajaxcall() {
ajax1();
ajax2();
}
function allajaxcomplete() {
// some code to be executed on completion of all ajax requests but after individual "ajaxcomplete1" and "ajaxcomplete2" functions
}
ajaxcall();
allajaxcomplete();
$.ajax returns a jQuery Deferred object (a promise). You then just have to use $.when to call a function when all those promises are resolved:
function ajax1(str) {
return $.ajax({
type: 'get',
data: "q=" + str,
url: 'foo.php',
success: function (result) {
//success!
ajaxcomplete1();
}
});
};
function ajax2(str) {
return $.ajax({
type: 'get',
data: "q=" + str,
url: 'foo.php',
success: function (result) {
//success!
ajaxcomplete2();
}
});
};
function ajaxcall() {
// store the promises (for clarity, you also could call the functions directly in the when)
var d1 = ajax1(),
d2 = ajax2();
// this function will be called only when both promises d1 and d2 are resolved
$.when(d1, d2).done(function(result1, result2){
// do stuff when both functions are done
// result1 and result2 are the result of the ajax calls inside your functions
allajaxcomplete();
});
}
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.
I would like to put an ajax call within a function since I use it repeatedly in multiple locations. I want a manipulated version of the response returned. Here's what I'm trying to do (greatly simplified).
a = getAjax();
$('body').append('<div>'+a+'</div>');
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
return response;
});
}
What's happening, however, is that the append function is running before "a" has been defined in the getAjax function. Any thoughts?
AJAX is asynchronous. This means that the code in the success handler is delayed until the request is successful, while the rest of the code continues as normal. You need to put the relevant code in the AJAX success handler:
getAjax();
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
$(document.body).append('<div>'+response+'</div>');
});
}
Note that I have also optimised your body selector by using the native Javascript document.body rather than using the standard tag selector.
Edit Callback version
function getAjax(callback) {
$.ajax({
type: 'GET',
url: 'someURL',
success: callback
});
}
You can now do the code inline using a callback function:
getAjax(function(response) {
$(document.body).append('<div>'+response+'</div>');
});
or
getAjax(function(response) {
alert(response);
});
or whatever.
The code inside the anonymous function call will be processed when the AJAX request is complete.
There are two ways to taggle this. one is to use the success callback:
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
AppendResponse(response);
});
the other is to set async to false http://api.jquery.com/jQuery.ajax/:
var a;
getAjax();
$('body').append('<div>'+a+'</div>');
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
async: false,
success: function(response) {
a = response;
});
}
Important note on non async:
Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation.
Why don't you return the response to another function in the success callback. This should handle your need for different responses:
getAjax();
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
AppendResponse(response);
});
}
function AppendResponse(response) {
$('body').append('<div>'+response+'</div>');
}
One suggestion I have is to pass a trigger to the command you want to run into the AJAX function so that it will run after AJAX has received a response-
a = getAjax();
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
inputText(response);
});
}
inputText(someText) {
$(document.body).append('<div>'+ someText +'</div>');
}
That way you can create if statements / other alternatives to continue to use the same AJAX command for different results
You can give a handler to the function getAjax(), but if the user needs the information for the next decision then why not wait using async: false?
function getAjax(handler) {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
handler(response);
});
};
function callGetAjax(response) {
if(response === undefined) {
getAjax(callGetAjax);
} else {
$('body').append('<div>'+response+'</div>');
}
}