I'm using a call back function which will check for 60secs. If file avaible then will return true else will return false. The call back function I'm calling after ajax call.. Here is code below :
$.ajax({
type: '..',
url: '..',
data: '..',
success: function(data) {
window.loadFile(data);
}
})
window.loadFile = function(filePath) { // I'm getting the data. Now passing to call back function
$.when(window.waitTillFileExistsAndLoad(filePath)).done(function(data) {
alert(data) // here data is giving me undefined..
});
}
var timer = 0;
window.waitTillFileExistsAndLoad = function(fileName) {
var checkFile;
return $.get(fileName, function(data) { // If file found..
timer = 0;
return true;
}).error(function() { // If file not found..
timer += 1;
if(timer == 30) {
timer = 0;
clearTimeout(checkFile);
return false;
} else {
console.log('error occured');
checkFile = setTimeout(function() {
window.waitTillFileExistsAndLoad(fileName);
}, 2000);
}
});
}
The issue is that when I'm using $.when() it's giving me undefined. Please suggest me what's wrong in my code.
Related
(My solution below)
I have several HTML elements with class .canvas-background of which information is stored in the database. I want to get the information of each element and process it via JavaScript. But somehow I can't pass the response of the AJAX request to another function. Here is what I've tried:
function initTabs() {
var tabs = loadTabInformation();
console.log(tabs); // (1)
// do something else
}
function loadTabInformation() {
var requests = new Array();
var tabs = new Object();
var counter = 0;
$(".canvas-background").each(function () {
var tabNumber = $(this).data("tab-number");
var request = $.ajax({
type: 'POST',
url: '../db/GetTabInformation.ashx',
data: String(tabNumber),
dataType: 'json',
contentType: 'text/plain; charset-utf-8'
})
.done(function (response) {
tabs[counter++] = response;
}).fail(function (jqXHR, textStatus, errorThrown) {
console.log("request error in loadTabInformation()");
console.log(textStatus);
console.log(errorThrown);
});
requests.push(request);
});
$.when.apply($, requests).done(function () {
console.log(tabs); // (2)
return tabs;
});
}
At (1) I get undefined, but at (2) everything seems to be alright.
THE SOLUTION:
Thanks to the answer and the link in the comment #Kim Hoang provided I got this working. The clue seemed to put the done() function in the calling function, that is initTabs() in my case. Another thing I got wrong was to try to do the logic that should be executed after the AJAX requests had finished outside the done callback function. They must be inside (makes sense, if you think about it). And a lot of conosle output helped, to see what function returns what kind of object.
function initTabs() {
var tabInfoRequest = loadTabInfo();
tabInfoRequest[0].done(function() {
var results = (tabInfoRequest[1].length > 1) ? $.map(arguments, function(a) { return a[0]; }) : [arguments[0]];
for (var i = 0; i < results.length; i++) {
// do something with results[i]
}
});
}
function loadTabInfo() {
var tabNumbers = new Array();
$(".canvas-background").each(function () {
tabNumbers.push($(this).data("tab-number"));
});
var requests = $.map(tabNumbers, function (current) {
return $.ajax({
type: 'POST',
url: '../db/GetTabInformation.ashx',
data: String(current),
dataType: 'json',
contentType: 'text/plain; charset-utf-8'
});
});
var resultObject = new Object();
resultObject[0] = $.when.apply($, requests);
resultObject[1] = requests;
return resultObject;
}
Note: I only did the resultObject-thing because I needed the array requests in the initTabs() function.
Thank you very much for helping me!
You do not return anything in loadTabInformation, so of course you will get undefined. You should do it like this:
function loadTabInformation() {
...
return $.when.apply($, requests);
}
function initTabs() {
loadTabInformation().done(function (tabs) {
console.log(tabs); // (1)
// do something else
});
}
I can’t seem to get this simple Parse query to work in my cloud code then() it works outside of this but when i place the code inside of this then function nothing happens. The variables are just placeholders for now in terms of testing but i have the default TestObject class you get when you start Parse from the beginning but for some reason it just keeps on returning nothing.
Here is the full function that i am currently using.
// Function which will get the data from all the links passed into the function
Parse.Cloud.define("myNews", function (request, response) {
var promises = _.map(import_io_keys, function (news_api_key) {
return Parse.Cloud.httpRequest({
method: 'GET',
url: "https://api.import.io/store/connector/" + news_api_key + "/_query?input=webpage/url:https%3A%2F%2Fwww.designernews.co%2Fnew&&_apikey=xxxxxxxxxxxxxxxxxx",
headers: {
'Content-Type': 'application/json;charset=utf-8'
}
}).then(function (httpResponse) {
result = JSON.parse(httpResponse.text);
var success = false;
var news_icon = "";
var news_source_name = "";
var query = new Parse.Query("TestObject");
query.find({
success: function(results) {
success = true;
news_icon = results[0].get("foo");
news_source_name = results[0].get("foo");
response.success("done" + news_icon);
},
error: function() {
success = false;
response.error("Query lookup failed");
}
});
for (var story in result.results) {
if(story.length > 0){
if (story["article_link/_text"] !== "" && story["article_link"] !== "" && story["article_time"] !== "") {
if(success){
// Do the stuff later
}
}
}
}
});
});
Parse.Promise.when(promises).then(function () {
console.log("Got all the stories");
response.success(newsJsonData);
}, function () {
response.error("No stories");
console.log("API KEY IS: " + request.params.keys);
});
});
A part of my chrome extension tests to see if the user is connected to the internet. It works once perfectly but after it runs, $.ajax === undefined and I don't know why. I don't see any setters which could modify $.ajax
var testInternet = function(callback) {
"use strict";
var testURLs, doCallback, i, failCount;
if (! callback) {
callback = function(){};
}
doCallback = true;
failCount = 0;
testURLs = [
"http://clients5.google.com/pagead/drt/dn/dn.js"
];
for (i= 0; i < testURLs.length; i++) {
testConnection(testURLs[i], function(success){
if (success && doCallback) {
doCallback = false;
callback(true);
return;
} else {
failCount += 1;
if (failCount === testURLs.length) {
callback(false);
return;
}
}
});
}
}
var testConnection = function(url, callback) {
"use strict";
$.ajax({
url: url,
timeout: 10000,
cache: false,
success: function(data) {
callback(true);
return;
},
error: function(data) {,
callback(false);
return;
}
});
}
It looks like because you are getting a .js file, jQuery automatically defaults the dataType to script, which will cause jQuery to evaluate the script being loaded. Specifying dataType: 'text' should prevent that unwanted behavior.
I have all my ajax calls in a custom JS file. And trust me there are alot of them!
I would like to implement a "retry on fail behavior" in all ajax calls.
Is there a way to do it like "interception"? Or do I have to do it one by one?
My fear here is that a future dev will forget to set the retry policy...
Sample ajax call:
$.ajax({
url: apiRoot + 'reservationItens?reservaId=' + idReservation + '&bagId=' + idBag,
type: 'PUT',
success: function () {
if (onSuccess != null) {
onSuccess();
}
},
error: function (x, y, z) {
if (onError != null) {
onError(x, y, z);
}
}
});
You can use ajaxError which takes a callback that is called on every ajax error.
Additionally you can add a boolean to the settings object and check for it in the callback which ensures that one failed request is only called a second time and not more.
$(document).ajaxError(function (event, jqxhr, settings) {
if(!settings.secondExec) {
settings.secondExec = true;
$.ajax(settings);
}
});
If desired add a timeout for the second request to increase the possibility that a random server or connection problem is resolved in the meantime:
setTimeout(function() {
$.ajax(settings);
}, 500);
If you want to exclude some requests just add another property to the request settings which you then use like secondExec is used in the example.
Here's a working jsfiddle.
I'd do it like this, with a recursive function:
function AjaxRetry(settings, maxTries, interval) {
var self = this;
this.settings = settings;
this.maxTries = typeof maxTries === "number" ? maxTries : 0;
this.completedTries = 0;
this.interval = typeof interval === "number" ? interval : 0;
// Return a promise, so that you can chain methods
// as you would with regular jQuery ajax calls
return tryAjax().promise();
function tryAjax(deferred) {
console.log("Trying ajax #" + (self.completedTries + 1));
var d = deferred || $.Deferred();
$.ajax(self.settings)
.done(function(data) {
// If it succeeds, don't keep retrying
d.resolve(data);
})
.fail(function(error) {
self.completedTries++;
// Recursively call this function again (after a timeout)
// until either it succeeds or we hit the max number of tries
if (self.completedTries < self.maxTries) {
console.log("Waiting " + interval + "ms before retrying...");
setTimeout(function(){
tryAjax(d);
}, self.interval);
} else {
d.reject(error);
}
});
return d;
}
}
And then usage is like this:
var settings = {
url: "https://httpbin.org/get",
data: {foo: "bar"},
contentType: "application/json; charset=UTF-8"
};
var maxTries = 3;
var interval = 500;
// Make your ajax call and retry up to 3 times,
// waiting 500 milliseconds between attempts.
new AjaxRetry(settings, maxTries, interval)
.done(function(data){
alert("My ajax call succeeded!");
})
.fail(function(error) {
alert("My ajax call failed :'(");
})
.always(function(resp){
alert("My ajax call is over.");
});
You can create api method for ajax calls, just like this one. In the ajaxApi function you can create your own handlers. For example for success or error events, thanks to this developer using this api can attach his handlers, without worrying what else handlers to attach.
function outerSuccesFN() {
console.log('outerSuccesFN');
}
function outerErroFN() {
console.log('outerErroFN');
}
function completeFn() {
console.log(completeFn);
}
function ajaxApi(url, dataType, data, timeout) {
var ajaxResults = $.ajax({
url: url,
dataType: dataType,
data: data,
timeout: timeout
});
function mySuccesFn() {
console.log('mySuccesFn');
}
function myErroFn() {
console.log('myErroFn');
}
return ajaxResults.done(mySuccesFn).fail(myErroFn);
}
var ajaxResult = ajaxApi('http://api.jquery.com/jsonp/', 'jsonp', {
title: 'ajax'
}, 15000);
ajaxResult.done(outerSuccesFN).fail(outerErroFN).always(completeFn);
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
jQuery: Return data after ajax call success
jQuery AJAX: return value on success
I can't figure out why goodPassword always returns undefined
I"m sure it's just a dumb mistake and will appreciate your answer
function foo(){
var goodPassword;
jQuery.ajax({
data: "action=Potato",
url: 'servletPotato',
timeout: 2000,
error: function() {
console.log("Failed to send ajax");
},
success: function(r) {
var data = jQuery.parseJSON(r);
if(data.aprovePassword == "true")
{
goodPassword = true;
}
else
{
goodPassword = false;
}
}
});
return goodPassword;
}
the ajax call is definitely working and data.aprovePassword definitely return from the servlet as "false"
Because goodPassword hasn't been assigned anything yet, since the XHR request executes after the function ends and that's why by the end of the function, nothing has been assigned. An alternative function would be:
function foo(successCallback) {
var goodPassword;
jQuery.ajax({
data: "action=Potato",
url: 'servletPotato',
timeout: 2000,
error: function() {
console.log("Failed to send ajax");
},
success: function(r) {
var data = jQuery.parseJSON(r);
if(data.aprovePassword == "true")
{
goodPassword = true;
}
else
{
goodPassword = false;
}
successCallback(goodPassword);
}});
}
The problem is that ajax requests are asynchronous, so the function is returning immediately after kicking off the jQuery.ajax call, and at that point goodPassword is still undefined.
Instead you need to do something like this:
function foo(callback) {
var goodPassword;
jQuery.ajax({
data: "action=Potato",
url: 'servletPotato',
timeout: 2000,
error: function() {
console.log("Failed to send ajax");
},
success: function(r) {
var data = jQuery.parseJSON(r);
if(data.aprovePassword == "true") {
goodPassword = true;
} else {
goodPassword = false;
}
callback(goodPassword);
}});
}
You would then call the function like this:
foo(function(goodPassword) {
console.log('goodPassword is ' + goodPassword);
});
You can't check the return value as the ajax call occurs after the function returns.
To perform two actions one on success and one on failure you need to do the following:-
var foo = function(goodCallback, badCallback){
jQuery.ajax({
data: "action=Potato",
url: 'servletPotato',
timeout: 2000,
error: function() {
console.log("Failed to send ajax");
},
success: function(r) {
var data = jQuery.parseJSON(r);
if(data.aprovePassword == "true")
{
goodCallback();
}
else
{
badCallback();
}
}
});
};
foo(
function() {
console.log('dude good password');
},
function() {
console.log('bad password');
}
);
or Have only 1 callback function takes the boolean value of goodpassword...