I have this jQuery function:
var searchResultsCounter = 0;
function searchPerson(filterText){
//code
$.ajax({
type: "GET",
dataType:"json",
url: "res/main.php",
data: { command : "loadPeople",
filter: filterText },
success: function( people ){
for(var i = 0; i< people.length; i++){
//code
}
searchResultsCounter = people.length;
console.log(searchResultsCounter);
}
});
console.log(searchResultsCounter);
return searchResultsCounter;
}
In the first console log, my searchResultsCoutner has a good value, at the second log, it becomes 0. Why is this happening?
The ajax request is executed asynchronously, so the success callback function which tries to alter the variable will be executed later.
Your function simply returns 0. You have to rewrite your code that it works an asynchronous way. One way would be to pass a callback function to searchPerson as a parameter.
Return from searchPerson() function the promise interface ($.ajax) and use returned result once deferred is resolved:
function searchPerson(filterText) {
//code
return $.ajax({
type: "GET",
dataType: "json",
url: "res/main.php",
data: {
command: "loadPeople",
filter: filterText
}
});
}
$.when(searchPerson(filterText)).done(function (data) {
/*SUCCESS*/
});
Related
Is it possible to pass data through a Ajax request to the Callback function without global variables?
for e.g. this request function should pass the passData through the callback function which should get also normal response data?!
function rquest(callback, passData){
$.ajax({
type: "POST",
url: someURL,
success: callback(passData)
});
};
function myCallback(data, passData){
var responseData = data;
var SomeOtherData = passData
//do Something
};
rquest(myCallback, "Hello World");
so "Hello World" should be in passData and data should be the normal response from server...if i do it in this way data is "Hello World" and passData is undefined.
Wrap the call to the provided callback in an anonymous function. Try this:
function rquest(callback, passData){
$.ajax({
type: "POST",
url: someURL,
success: function(data) {
callback(data, passData)
}
});
};
function myCallback(data, passData) {
var responseData = data;
var SomeOtherData = passData
//do Something
};
rquest(myCallback, "Hello World");
I found the answer in the below link - some more patterns are available to achieve this -
Adding some of the content from the reference answer.
The pattern you'd like to use could work if you create a closure inside your rssToTarget function:
function rssToTarget(element) {
return function (xmlData) {
// work with element and the data returned from the server
}
}
function doSomething(url, elem) {
$.ajax({ type: "GET",
url: url,
dataType: "xml",
success: rssToTarget(elem)
});
}
When rssToTarget(elem) is executed, the element parameter is stored in the closure, and the callback function is returned, waiting to be executed.
Reference link https://stackoverflow.com/a/1194187/3082706
I am trying to call two different functions in third function but one after the other.One function has ajax call, whose values are used in other function. it is step by step process. I don't want to use one into the other.
function f1()
{
// ajax call
return r1
}
function f2(r2)
{
// do some of the work based on r2
}
function f3()
{
$.when(f1()).done(function(data){
f2(data)
});
}
I also tried with $.when().then(); but still of no use.
Thanks, in advance.
UPDATE :- Below is the answer for my Question based on solution provide by #dreamweiver.
var json_data = '';
function f1()
{
$.ajax({
url: "test.php",
method: "POST",
async : false,
data: { },
success:function(data){
json_data = eval(data);
}
});
}
function f2(t)
{
console.log("values is "+t);
}
function f3()
{
$.when(f1()).done(function(){
f2(json_data);
});
}
Thanks everyone for your feedbacks.
Try this way, I have tested locally and it works perfectly
function deferredCalls () {
var jsonData = '';
var f1 = function ()
{
// ajax call
$.ajax({
url: "test.html",
method: "POST",
data: { id : menuId }
}).done(function(data) {
jsonData = data; //set the data
});
}
var f2 = function (data)
{
// do some of the work based on data
if(!!data){
//process the data
}
}
$.when(f1).done(function(){
f2(jsonData);
});
}
f1 function is called first which would in turn make a ajax request and return data on success, which is set to a function scope variable jsonData. Once this process is completed, f2 would be called which will start using jsonData, which is nothing but the data received from f1 function call.
This should be working:
function f1() {
// Or some other Ajax request that returns a promise
return $.getJSON('path/to/your/service');
}
function f2(r2) {
// ...
}
f1().done(f2);
My question is relatively straight forward.
I have an array of deferreds waiting to be returned, the code is like this:
var deferreds = [];
for(var i = 0; i < 5; i==){
deferreds.push(getOneResult(params));
}
var deferreds = [];
for(var i = 0; i < 5; i==){
deferreds.push(getOneResult(params));
}
The "getOneResult" function looks like this:
function getOneResult(params){
return $.ajax({
url: myURL,
data: params
});
}
It worked fine until one day I decided to let the "getOneResult" function to execute another ajax process and then using the result from this ajax process to get the result, so now my problematic code looks like this:
function getOneResult(params){
$.ajax({
url: myOtherURL,
data: params,
success: function(){
var result = arguments;
return $.ajax({
url: myURL,
data: arguments
});
}
});
}
Then all of a sudden all the items in "deferreds" array become "undefined". I am sure what I am doing sounds not right but is there anyway for me to run an ajax process before returning the deferred?
try returning the second promise. The original promise will now use the wrapped, second ajax promise.
function getOneResult(params){
return $.ajax({
url: myOtherURL,
data: params
}).then(function() {
return $.ajax({
url: myURL,
data: arguments
});
});
}
I have that code :
for (var i = 0; i < $total_files; i++) {
$.ajax({
type: 'POST',
url: 'uploading.php',
context: $(this),
dataType: 'json',
cache: false,
contentType: false,
processData: false,
data: data_string,
success: function(datas) {
//does something
},
error: function(e) {
alert('error, try again');
}
});
}
It uploads images very well but the problem is that I can't find a way to upload the images one by one, I tried to put the option async to false but it freezes the web browser until all images are uploaded which is not what I want, I want to emulate somehow this "async : false" option to perform the same thing but without freezing the web browser.
How to do this ?
You can create an array of promises so that once all promises are resolved you can run your all done code.
var promises = [];
for (var i = 0; i < $total_files; i++){
/* $.ajax returns a promise*/
var request = $.ajax({
/* your ajax config*/
})
promises.push( request);
}
$.when.apply(null, promises).done(function(){
alert('All done')
})
DEMO
For jQuery 3.x+ and modern browser that support native Promise, Promise.all could be used this way:
var promises = [];
for (var i = 0; i < $total_files; i++) {
// jQuery returns a prom
promises.push($.ajax({
/* your ajax config*/
}))
}
Promise.all(promises)
.then(responseList => {
console.dir(responseList)
})
If your files are already stored in a list then you could use map instead of a loop.
var fileList = [/*... list of files ...*/];
Promise.all(fileList.map(file => $.ajax({
/* your ajax config*/
})))
.then(responseList => {
console.dir(responseList)
})
Populate an array with each call and call the next item when the previous is done.
You could try something like that:
window.syncUpload = {
queue : [],
upload : function(imagesCount) {
var $total_files = imagesCount, data_string = "";
/* Populates queue array with all ajax calls you are going to need */
for (var i=0; i < $total_files; i++) {
this.queue.push({
type: 'POST',
url: 'uploading.php',
context: $(this),
dataType: 'json',
cache: false,
contentType: false,
processData: false,
data: data_string,
success: function(datas) {
//does something
},
error: function(e){
alert('error, try again');
},
/* When the ajax finished it'll fire the complete event, so we
call the next image to be uploaded.
*/
complete : function() {
this[0].uploadNext();
}
});
}
this.uploadNext();
},
uploadNext : function() {
var queue = this.queue;
/* If there's something left in the array, send it */
if (queue.length > 0) {
/* Create ajax call and remove item from array */
$.ajax(queue.shift(0));
}
}
}
Just call it using
syncUpload.upload(NUMBER_OF_IMAGES);
I would try jQuery.when so you can still use asynchronous call but deferred, something like :
jQuery(document).ready(function ($) {
$.when(
//for (var i = 0; i < $total_files; i++) {
$.ajax({
// ajax code
})
//}
).done(function () {
// perform after ajax loop is done
});
}); // ready
EDIT : ajax iteration should be done outside $.when and pushed into an array as proposed by charlietfl's answer. You may use an (asynchronous) ajax call and defer it inside $.when though, see JSFIDDLE
In one statement with jquery
$.when.apply(null, $.map(/*input Array|jQuery*/, function (n, i) {
return $.get(/* URL */, function (data) {
/* Do something */
});
})).done(function () {
/* Called after all ajax is done */
});
I want to call three functions someTask1, someTask2 and someTask3 in that order. However, the function someTask2 involves Ajax call, and keep calling itself recursively using setTimeout unless a desired value is return. The code looks like this:
doListOfTasks: function(myparam){
var someObj = someTask1(myParam);
someTask2(someObj);
someTask3(someObj);
},
someTask2: function(someObj){
$.ajax({
url: "someUrl.do",
type: "POST",
data: ({"id": rowObject.instanceId}),
dataType: "json",
async:false,
success: function(res){
if(res.prop1 != 'desired'){
setTimeout(function(){someTask2(someObj);}, 2000);
}
}
}
);
},
As you might have guessed, the execution of this code does not wait for someTask2 to return before calling someTask3.
I want the code inside doListOfTasks to be executed sequentially. How can I do that?
Also, I do not want to hard-code someTask3 in success callback. E.g. I do not want to do this:
success: function(res){
if(res.prop1 != 'desired'){
setTimeout(function(){someTask2(someObj);}, 2000);
}else{
someTask3(someObj);
}
}
How can achieve this?
Thanks
Edit#1
The problem is not being able to call the functions... but the problem is synchronization. I want someTask2 to finish whatever it's doing, and only then someTask3 is called.
someTask2 calls itself repetitively using setTimeout... I guess this triggers a new thread and someTask2 is returned after first call... triggering someTask3 in main thread. However, separate thread spawns (and gets killed) in each call setTimeout until the desired criteria is met.
That's why, while the someTask2 still looping, the call to someTask3 triggers.
Not sure how correct I am.
You can achieve this using a Deferred in jquery:
$.when(someTask1(), someTask2(), someTask3()).then(successFunc, errorFunc);
You need to return a custom made .Deferred object with a promise value.
someTask2: function(someObj)
{
var def = $.Deferred();
$.ajax({
url: "someUrl.do",
type: "POST",
data: ({"id": rowObject.instanceId}),
dataType: "json",
async:false,
success: function(res){
if(res.prop1 != 'desired'){
setTimeout(function(){someTask2(someObj);}, 2000);
}
else
{
def.resolve(res);
}
}
}
);
return def.promise();
}
So for example:
function someTask1()
{
var def = $.Deferred();
def.resolve('i\'m data resolved from task1');
return def.promise();
}
function someTask2(someObj)
{
var def = $.Deferred();
var count = 0;
var f = function() {
console.log(++count);
if (count > 2) {
def.resolve('whoop we got the value we wanted in task 2 after many tries: ' + count);
}
else
setTimeout(f, 1000);
};
f();
return def.promise();
}
function someTask3()
{
var def = $.Deferred();
def.resolve('and hello from task3!');
return def.promise();
}
var success = function(x) {
console.log('success:', arguments);
};
var error = function() {
console.log('oh no an error occured in one of the tasks.');
};
$.when(someTask1(), someTask2(), someTask3()).then(success , error);
Will show
1
2
3
success: ["i'm data resolved from task1",
"whoop we got the value ...k 2 after many tries: 3",
"and hello from task3!"]
fiddle available: http://jsfiddle.net/garreh/29SW7/
You could pass a callback to someTask2. For example:
someTask2: function(someObj, callback){
$.ajax({
url: "someUrl.do",
type: "POST",
data: ({"id": rowObject.instanceId}),
dataType: "json",
async:false,
success: function(res){
if(res.prop1 != 'desired'){
setTimeout(function(){someTask2(someObj, callback);}, 2000);
} else {
if (callback != null) {
callback();
}
}
}
}
);
}
Then just pass someTask3 as the callback:
someTask2(someObj, function (){ someTask3(someObj); });