How to execute an action after all Ajax requests complete using jQuery - javascript

I have been trying to accomplish this where I have two Ajax calls. I want to execute another Ajax call ONLY when the first two are completely done. However, when I make the call to my first two, the third one is being executed as well. Below is my code.
/**
* Triggers all the partners to search for offers.
*/
function PREQUAL_OFFERS() {
var hughes = HUGHES();
var ctl = CTL();
$.when(hughes, ctl).then(function () {
ENGINE_OFFERS(); // Executes after all previous Ajax calls are done.
});
}
function ATT() {}
function HUGHES() {
console.log("Initialized hughes()");
var data = $("#searchPackages").serialize();
var requestOffers = $.ajax({
url : "/isgov3/index.php/HUGHES/ajax/PreQual",
type : "POST",
dataType : "html",
cache : false,
data : data,
});
requestOffers.success(function (data) {});
requestOffers.fail(function (jqXHR, error, errorThrown) {});
}
function CTL() {
console.log("Initialized CTL()");
var data = $("#searchPackages").serialize();
var requestOffers = $.ajax({
url : "/isgov3/index.php/CTL/ajax/PreQual",
type : "POST",
dataType : "html",
cache : false,
data : data,
});
requestOffers.success(function (data) {});
requestOffers.fail(function (jqXHR, error, errorThrown) {});
}
function ENGINE_OFFERS() {
console.log("Called Engine");
var Offers = $.get({
url : "/isgov3/index.php/ENGINE/engine",
dataType : "html",
cache : false,
});
Offers.success(function (data) {
$("#MyTab-Menu_tab_12").html(data);
});
Offers.fail(function (jqXHR, error, errorThrown) {});
}

HUGHES() and CTL() will both have to return a deferred/promise for $.when() to use, such as the jqXHR provided by $.ajax():
function HUGHES(callback) {
// ...
var requestOffers = $.ajax({ ... });
// ...
return requestOffers;
}
function CTL(callback) {
// ...
return requestOffers;
}
Without a return statement in either function, var hughes and var ctrl are both being assigned undefined, which $.when() treats as an immediate resolution/success value:
$.when(undefined, undefined).then(function () {
console.log(arguments); // { 0: undefined, 1: undefined }
});

You can create a callback function for each in such way a certain stuff will wait for that other stuff to finish before execution. So in this case ENGINE_OFFERS will only be executed if HUGHES and CTL are already done.
function PREQUAL_OFFERS() {
HUGHES(function(data) {
CTL(function(data) {
ENGINE_OFFERS();
});
});
}
function ATT() {}
function HUGHES(callback) {
console.log("Initialized hughes()");
var data = $("#searchPackages").serialize();
var requestOffers = $.ajax({
url : "/isgov3/index.php/HUGHES/ajax/PreQual",
type : "POST",
dataType : "html",
cache : false,
data : data,
});
requestOffers.success(function (data) { callback(data); });
requestOffers.fail(function (jqXHR, error, errorThrown) { callback(error); });
}
function CTL(callback) {
console.log("Initialized CTL()");
var data = $("#searchPackages").serialize();
var requestOffers = $.ajax({
url : "/isgov3/index.php/CTL/ajax/PreQual",
type : "POST",
dataType : "html",
cache : false,
data : data,
});
requestOffers.success(function (data) { callback(data); });
requestOffers.fail(function (jqXHR, error, errorThrown) { callback(data); });
}
function ENGINE_OFFERS() {
console.log("Called Engine");
var Offers = $.get({
url : "/isgov3/index.php/ENGINE/engine",
dataType : "html",
cache : false,
});
Offers.success(function (data) {
$("#MyTab-Menu_tab_12").html(data);
});
Offers.fail(function (jqXHR, error, errorThrown) {});

Related

Knockout observable updates reflected only in inner scope

I'm trying to update an Observable from within an Ajax callback using...
function LocaleVM() {
const self = this;
self.Language = ko.observable("en");
self.Strings= ko.observable();
self.toggleLanguage = function () {
const lang = self.Language() === 'en' ? 'es' : 'en';
console.log(self.Language());
console.log(lang);
$.ajax({
url: `/${lang}`,
method: 'GET',
success: function (data, textStatus, xhr) {
self.Language(lang);
console.log(self.Language());
console.log(lang);
//===============================================
... update strings ...
},
error: function (xhr, textStatus, errorThrown) {
console.log(errorThrown);
}
});
}
}
And that is the console output every time toggleLanguage gets called...
en
es
es
es
Which seems to be updating fine within the call back but not outside. What seems to be the problem here?
It looks like you're never actually updating the value of the Language observable.
Here is a condensed version of your script...
self.toggleLanguage = function () {
const lang = self.Language() === 'en' ? 'es' : 'en';
$.ajax({
url: `/${lang}`,
method: 'GET',
success: function (data, textStatus, xhr) {
self.Language(lang); // <<< THIS IS ALWAYS THE SAME VALUE.
console.log(self.Language());
console.log(lang);
}
});
}
I can only assume the values you're fetching in that AJAX request but don't you want something like this?
self.toggleLanguage = function () {
$.ajax({
url: `/${lang}`,
method: 'GET',
success: function (data, textStatus, xhr) {
self.Language(data); // <<< USE THE NEWLY-FETCHED VALUE.
console.log("Previous value: " + lang);
console.log("Current value: " + self.Language());
}
});
}

How to create a loop within my function and then send it to my JSON file

So, I have my JSON file, but I need to send a certain URL to my JSON aswell with a loop.
this is where I set everything:
function setMainObjectArray() {
var exercises = [];
var eBlocks = $('.eBlock');
eBlocks.each(function(i, eBlock) {
var exObject = {
word: $(eBlock).find('input.ExerciseGetWordInput').val(),
syllables: []
};
$(eBlock).find('input.syllable').each(function(j, syll) {
exObject.syllables.push($(syll).val());
});
exercises.push(exObject);
});
return exercises;
}
this is my ajax save function:
function saveExerciseAjaxCall() {
console.log(setMainObjectArray());
$.ajax({
url: 'saveJson.php',
type: 'POST',
data: {
id: getUrlParameter('id'),
getExerciseTitle: $('#getExerciseTitle').val(),
language: $('#languageSelector').val(),
application: 'lettergrepen',
'main_object': {
title: $('#getExerciseTitle').val(),
language: $('#languageSelector').val(),
exercises: setMainObjectArray()
},
dataType: 'json'
}
}).done(function(response) {
}).fail(function(jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
console.log(errorThrown);
console.log(textStatus);
});
}
and I think I need to loop something like this through my function setMainObjectArray()
var audioId = MEDIAARRAY.audio.lowercase.indexOf(exObject['exerciseGetWordInput'].toLowerCase() + '.mp3');
var audio_link = '';
if (audioId > -1) {
exObject['audio'] = 'https://TheUrlServer' + MEDIAARRAY.audio.path + MEDIAARRAY.audio.files[audioId];
}
But I have no idea how to implement this into my function setMainObjectArray. I am not entirely sure if the loop is even written the correct way, i'm quite new to javascript and from there on to put it in my ajax call (since it's a link).

External method from an AJAX callback in JavaScript & jQuery

I have a function in JS & jQuery that fires an AJAX call and it has a callback block to let me know when it's finished:
function ajaxCall(url, type, dataType, dataToSend, callback) {
if (dataType == undefined) dataType = "json";
if (dataToSend == undefined) dataToSend = null;
$.ajax({
url: url,
type: type,
dataType: dataType,
contentType: "application/json",
data: dataToSend,
async: true,
success: function (result) {
callback(result);
},
error: function (data, status) {
console.error("Server Error: " + status);
}
});
}
I am accessing it like so, but using external functions like showAjaxLoader() just doesn't work! it says this function is undefined:
function registerUser(data) {
ajaxCall(pathServiceRegister, "POST", undefined, JSON.stringify(data), function (result) {
// SOME CODE THAT RUNS WHEN IT'S COMPLETE
// External method:
showAjaxLoader(false); // Doesn't work
});
});
function showAjaxLoader(show) {
var loader = $('.ajax-loader');
if (show) {
loader.fadeIn("fast");
} else {
loader.fadeOut("fast");
}
}
What am I doing wrong?
Thanks :)
Worked out some sample. this may be good practice. Try this :
$(document).ready(function() {
$("button").click(function() {registerUser();});
});
var Scallback = function(arg) {
alert("Success :"+arg);
showAjaxLoader(true);
}
var Ecallback = function(arg) {
alert("Err :"+arg);
showAjaxLoader(true);
}
function showAjaxLoader(show) {
var loader = $('.ajax-loader');
if (show) {
loader.fadeIn("fast");
} else {
loader.fadeOut("fast");
}
}
function ajaxCall(url, type, Scallback, Ecallback) {
$.ajax({
url : url,
type : type,
async : true,
success : function(result) {
Scallback(result);
},
error : function(data) {
Ecallback(data)
}
});
}
function registerUser()
{
ajaxCall(pathServiceRegister, "GET", Scallback, Ecallback);
}
Have you tried to do something like:
var that = this;
function registerUser(data) {
ajaxCall(pathServiceRegister, "POST", undefined, JSON.stringify(data), function (result) {
// SOME CODE THAT RUNS WHEN IT'S COMPLETE
// External method:
that.showAjaxLoader(false);
});
});
Declare your method like this
var obj = {
showAjaxLoader : function(show) {
var loader = $('.ajax-loader');
if (show) {
loader.fadeIn("fast");
} else {
loader.fadeOut("fast");
}
}
}
Then inside ajax, call obj.showAjaxLoader(false); This may work.

Execute callback function inside javascript object

I want to execute a callback function inside an object. I don't know if there is something wrong in the way I'm doing this.
I've googled for a solution, also searched on stackoverflow but couldn't find anything similar to the way I'm coding this.
PHPGateway.js
var PHPGateway = {
opt_friendlyURL: true,
opt_folder: 'ajax/',
callback_function: null,
useFriendlyURL: function (bool) {
this.opt_friendlyURL = bool;
},
setFolder: function (folder) {
this.opt_folder = folder;
},
send: function (service, method, data, callback) {
var url,
json_data = {};
if (this.opt_friendlyURL) {
url = this.opt_folder + service + '/' + method;
} else {
url = this.opt_folder + 'gateway.php?c=' + service + '&m=' + method;
}
if (data != undefined) {
json_data = JSON.stringify(data);
}
this.callback_function = (callback == undefined) ? null : callback;
$.ajax({
method: 'POST',
url: url,
data: {data: json_data},
success: this.ajax_success,
error: this.ajax_error
});
},
ajax_success: function (returned_object) {
if (this.callback_function != null) {
this.callback_function(returned_object.error, returned_object.data);
}
},
ajax_error: function () {
this.callback_function.call(false, {});
}
};
Then inside the HTML file that loads PHPGateway.js, I've the following code:
<script>
function submit_handler(event) {
event.preventDefault();
form_submit();
}
function form_callback(error, data) {
if(error == null) {
alert(data.text);
}
}
function form_submit() {
var data = {
status: $('#inStatus').val(),
amount: $('#inAmount').val(),
id: $('#inBudgetID'). val()
}
PHPGateway.send('budget', 'status', data, form_callback);
}
$('form').one('submit', submit_handler);
</script>
I get an error on this.callback_function(returned_object.error, returned_object.data);, the error is Uncaught TypeError: Object # has no method 'callback_function'.
What am I doing wrong?
Is this the best way to do it?
Thank You!
Based on minitech answer, I've updated PHPGateway.js like this. I've omitted the parts that weren't updated.
var PHPGateway = {
// Omitted code
send: function (service, method, data, callback) {
var url,
json_data = {},
that = this;
if (this.opt_friendlyURL) {
url = this.opt_folder + service + '/' + method;
} else {
url = this.opt_folder + 'gateway.php?c=' + service + '&m=' + method;
}
if (data != undefined) {
json_data = JSON.stringify(data);
}
this.callback_function = (callback == undefined) ? null : callback;
$.ajax({
method: 'POST',
url: url,
data: {data: json_data},
success: function(data, textStatus, jqXHR) {
that.ajax_success(data, textStatus, jqXHR);
},
error: function(jqXHR, textStatus, errorThrown) {
that.ajax_error(jqXHR, textStatus, errorThrown);
}
});
},
ajax_success: function (data, textStatus, jqXHR) {
if (this.callback_function != null) {
this.callback_function(true, data.data);
}
},
ajax_error: function (jqXHR, textStatus, errorThrown) {
this.callback_function.call(false, {});
}
};
Now it works!!!
In your call to $.ajax, you need to add a context option:
$.ajax({
method: 'POST',
url: url,
data: {data: json_data},
context: this,
success: this.ajax_success,
error: this.ajax_error
});
Your this variable in your Ajax success and error handlers are not pointing to the object you think they are. The context option to $.ajax() sets which object this points to in the Ajax callbacks.
Here’s your problem:
$.ajax({
method: 'POST',
url: url,
data: {data: json_data},
success: this.ajax_success,
error: this.ajax_error
});
When you set success and error to methods on this, they don’t keep their this. When a JavaScript function is called, it gets bound a this:
someFunction(); // this is undefined or the global object, depending on strict
someObject.someFunction(); // this is someObject
The built-in .call, .apply, and .bind of Function objects help you override this.
In your case, I think jQuery binds this to the Ajax object – a good reason to both not use jQuery and always use strict mode.
If you can guarantee or shim ES5 support, bind is an easy fix:
$.ajax({
method: 'POST',
url: url,
data: {data: json_data},
success: this.ajax_success.bind(this),
error: this.ajax_error.bind(this)
});
Which is equivalent to this if you can’t:
var that = this;
$.ajax({
method: 'POST',
url: url,
data: {data: json_data},
success: function() {
that.ajax_success.apply(that, arguments);
},
error: function() {
that.ajax_error.apply(that, arguments);
}
});
And now, a tip for you: don’t namespace, and if you do, don’t use this. this is great for objects that are meant to be constructed. What would seem more appropriate is something like this, if you really have to:
var PHPGateway = (function() {
var callbackFunction;
var options = {
friendlyURL: true,
…
};
…
function send(service, method, data, callback) {
…
}
…
return { send: send };
})();

How to optimize (minimize) jQuery AJAX calls

I have over 50 AJAX calls from different functions of my code. All these calls have a similar structure with different data/url/callback params:
var jqXHR = $.post('/dba/port.php', {
mode: "del_wallfunds",
pdata: cdata,
wname: wName
},
function (data) {}, "json")
.done(function (data) {
var msg = data.msg;
if (msg.indexOf("Error") == -1) {
alertify.success(msg);
delSelected(selGroup);
} else {
alertify.error(msg);
}
})
.fail(function () {
alertify.error("Error .....");
});
I am thinking how to write a function that would return that var jqXHR to minimize the total size of the code. It is not a problem to pass all static variables like URL, error strings etc. But the problem is that all callback functions on ".done" are different and I don't know how to pass these callback functions as variables.
One way would be to call a single "universal" function on .done and pass a "switch" variable to that function, but it doesn't seem to be an elegant solution.
Any suggestions how to it in some elegant way?
Thanks
Either pass the done callback function as an argument when calling your function:
function ajaxCall(url, data, doneCallback) {
return $.post(url, data, doneCallback, "json").fail(...);
// or
return $.post(url, data, function() {}, "json").done(doneCallback).fail(...);
}
var jqXhr = ajaxCall('yoururl.php', {key: 'value'}, function(data) {
// do something
});
Or return the jqXhr object from the function, and assign the done callback then:
function ajaxCall(url, data) {
return $.post(url, data, function() {}, "json").fail(...);
}
var jqXhr = ajaxCall('yoururl.php', {key: 'value'});
jqXhr.done(function(data) {
// do something
});
Alternatively switch to using jQuery.ajax() instead, and pass the entire options object in:
function ajaxCall(options) {
return $.ajax(options).fail(...);
}
var jqXhr = ajaxCall({
url: 'yoururl.php',
data: {key: 'value'},
dataType: 'json'
});
jqXhr.done(function(data) {
// do something
});
You can try to :
turn "request successfully returned a treatment error" into a "rejected request",
put the "alertify" processing in a common callback
Here is a sketch of what this could give :
function myAjaxApi(url, data){
var myAjaxCall = $.post(url, data, function (data) {}, "json")
.then(function (data) {
// using .then : change "request succesful with error state"
// to "rejected state"
var msg = data.msg;
if (msg !== undefined && msg.indexOf("Error") >= 0) {
var dfd = $.Deferred();
// try to match the same signature as the "error" option
dfd.reject(this, msg);
return dfd;
} else {
return data
}
});
myAjaxCall.done(function(data){
if (data.msg) {
alertify.success(data.msg);
}
}).fail(function (jqxhr, msg) {
if (!msg) { msg = "Error ....."; }
alertify.error(msg);
});
return myAjaxCall;
}
//usage
myAjaxApi('/dba/port.php', {mode: "del_wallfunds", pdata: cdata, wname: wName})
.done(function (data) {
// the ".done()" queue will not be executed if msg contains "Error" ...
delSelected(selGroup);
});
Some parts should be written with more care ; the above example is meant to illustrate how you can wrap your repeated ajax calls inside a common api.

Categories

Resources