jQuery wait for a function to complete before new fires - javascript

I have two functions in jQuery that I want to fire in a specific order. The first function is an ajax function which updates a partial view. The other one is supposed to do some styling on the partial view, once the ajax function has completed - this function takes a parameter.
ajaxFunction();
stylingFunction(params);
I have tried the following:
ajaxFunction(function() {
stylingFunction(params)
});
Also, I have tried to use a callback:
ajaxFunction(stylingfunction(params));
ajaxFunction(callback)
{
//Do update
callback()
}
None of these do however work. The styling appears shortly where after it dissapears because the partial view is getting updated. Where am I going wrong here?
Both functions are written in my "parent" view.

You can use .done() and .fail() chained to the $.ajax call ...
I created a couple callback functions with psuedo-code inside the successCallback() since you said you only need to run the styling function "sometimes". You will want to test whatever condition inside that function to determine if you want to run the styling function. Hope this helps.
(function($) {
$(function() { //document.ready
$.ajax({ cache: false,
url: "/blah/vlah/lah",
data: { somedata: somedata }
})
.done(successCallback)
.fail(failCallback);
});
function successCallback(data) {
if (someCondition) {
stylingFunction(params);
}
};
function failCallback(jqXHR, status, error) {
console.log(jqXHR);
console.log(error);
console.log(status);
};
})(jQuery);
I created another gist which handles ajax event delegation, you may want to review and incorporate anything that seems helpful to your situation.
https://gist.github.com/inceptzero/a753d020648f49da90f8
I also created this gist on github for an ajax request queue which is a bit more elegant and robust.
https://gist.github.com/inceptzero/e64756f9162ca6aeeee5

Since you are using jQuery you could const ajaxFunc = callback => $.ajax({...}).done( data => callback) Also you could use async/await. You can read more about it on MDN.

Related

jquery plugin - make ajax call chainable

I am trying to write a jquery plugin.
Now, I would like to use an ajax-call in one of the functions of this plugin.
However it should be chainable, meaning in this case that the ajax-call should be executed and only after something was returned, the return should happen.
I tried different things but so far I could not make it so that the second function in the chain is really executed after the return value of the ajax call was retrieved;
In this version (see below) I can use
$(document).createDatabase().message();
So, chaining works.
But looking at the console log – the message() function is executed before the ajax-call in createDatabase() is finished.
How can I make it so that
$(document).createDatabase().message();
first returns the output/return of the ajax-call that is inside createDatabase() and only after that message() is executed?
Code:
(function($) {
$.fn.createDatabase = function(options) {
// Plugin options defaults
var settings = $.extend({
name: 'NA',
onExit: function() {} // callback function
}, options);
$.ajax({
method: "POST",
url: "plugin/php/createDatabase.php",
data: settings
})
.done(function(msg) {
console.log("createDatabase executed with message: " + msg);
settings.onExit.call();
});
return this;
};
$.fn.message = function() {
console.log('this should appear after the console-log message of createDatabase');
return this;
}
}(jQuery));
Thank You!
You could do a couple of things, but they are all a bad idea. The reason is that these are two separate jQuery plugins - a plugin should be capable of working on its own. There is no guarantee or reason that somebody won't do .message().createDatabase(). If you need to guarantee the order of execution, then you should use just one plugin. One possible way would be to pass message inside options when you call .createDatabase(options), and then run message when the call is done. Like so
$(document).createDatabase({
message: function() {...}
});
...
var promise = $.ajax({
method: "POST",
url: "plugin/php/createDatabase.php",
data: settings
})
.done(function(msg) {
console.log("createDatabase executed with message: " + msg);
settings.onExit.call();
});
...
if ( settings.message )
promise.done( settings.message.bind(this) );
I tried different things but so far I could not make it so that the second function in the chain is really executed after the return value of the ajax call was retrieved;
The second function executes when the first one finishes. The first one finishes with return this, but this happens before the ajax call is done because ajax calls are asynchronous.

Adding in loading and error text with jQuery Ajax

I was wondering how easy is to to expand this code so that it shows an error if it cannot connect and whilst it is connecting it shows a loading text or loading image. It seems pretty standard behaviour on ajax driven sites but I haven't found much useful information online on how to achieve it.
$(document).ready(function () {
var loadUrl = 'http://sheldonbrown.com/web_sample1.html';
$("#close").click(function () {
$("#country_slide").hide();
});
$("#country").click(function () {
$("#country_slide").show();
$("#country_slide").html(ajax_load).load(loadUrl);
});
});
Depending on the context of your application, you can subscribe callbacks to fire on certain global AJAX events. Say, whenever an AJAX call starts, or whenever an AJAX call throws an error.
$(document)
.ajaxStart(function (e) {
$('body').showMyAwesomeLoadingGIF();
})
.ajaxComplete(function (e) {
$('body').hideMyAwesomeLoadingGIF();
});
This will cause those two callback functions to fire during the appropriate lifecycle events on every AJAX call made in your document.
If, for some reason, you want a certain AJAX call not to trigger your global AJAX event handlers, you can specify that that particulat AJAX call is not global.
$.ajax({
global : false,
// blah
})
More information on global AJAX event handling here.
EDIT
If you want to maintain a bit more granular control, there's $.ajaxSetup(), but since jQuery themselves discourages its use, I'm thinking you might be left with having to fashion your own solution.
Personally, I'd use a wrapper function with a closure to set my custom option values if they're something you expect to do repeatedly.
var ajax = (function () {
var defaults = { };
return function (opts) {
opts = $.extend({}, defaults, opts);
// place what you want to happen when an AJAX call starts here
return $.ajax(opts)
// place corresponding events here
.done(function (m) {
})
.fail(function (x,s,e) {
})
.complete(function (m) {
});
};
}());
// then use that in your code like how you'd use $.ajax():
ajax({
url : 'http://my.domain.com/api/users',
type : 'GET'
}).done(function (m) {
console.log('Done GET users.');
});
// ... and you can be sure that it has default options and default event handlers,
// while being able to add on to them if you wish.

forcing one javascript function to wait to run until the first has finished

Afternoon all, I am running into an issue where i need to run one function, then after that is finished, run the next, and do this for four functions, i have been at this for a while trying to find the correct syntax to layout my function calls in and cant seem to find anything to address this specific scenario.
html:
<div id = "putcontenthereafterajax">
</div><!--end putcontenthereafterajax-->
<div id = "putfooterhereafterajax">
</div<!--end putfooterhereafterajax-->
jquery:
$(window).load(function() {
function preload(arrayOfImages) {
$(arrayOfImages).each(function(){
$('<img/>')[0].src = this;
//alert("I cached "+this+"");
});
$('#progressbarinner').css("width","200px");//change the width of the inner progress bar div
}
function changecss(){
$('.hidetillcache').css("visibility","visible");//make the page visible
$('#loadingscreen').fadeOut("slow");
}
function contentajax(){
$.post("templates/content.php",
{
whatamidoing:"imgettingthecontent"
},
function(data){
$('#putcontenthereafterajax').after(''+data+'');
$('#progressbarinner').css("width","400px");//change the width of the inner progress bar div
});
}
function footerajax(){
$.post("templates/footer.php",
{
whatamidoing:"imgettingthefooter"
},
function(data){
$('#putfooterhereafterajax').after(''+data+'');
$('#progressbarinner').css("width","500px");//change the width of the inner progress bar div
});
}
preload([
'images/careers.jpg',
'images/careers.png',
'images/contact.jpg',
'images/facebook.png',
'images/footer.png',
'images/footerblack.png',
'images/footergrey.png',
'images/home.jpg',
'images/media.jpg',
'images/media.png',
'images/myitv3.jpg',
'images/newindex.jpg',
'images/newindex.png',
'images/services.jpg',
'images/twitter.png'
], contentajax(), footerajax(), csschanges());
});
basically i have a loading bar that fills up a bit after each function is finished which in turn requries each function to be ran one after another in the correct order, all the functions do work, the caching and the ajax and even the css changes work. however i cant seem to find a way to force them in the right order and to wait to run until the previous is finished in order to compliment the loading bar. Anyone have any ideas?
You want to chain asynchronous function calls.
Use jQuery's deffered.then method :
ajax functions, like $.ajax(), $.post(), $.get(), return a Deferred object.
You can use this in your case :
function contentajax(){
// add the return instruction to return the Deferred object
return $.post("templates/content.php", {... });
}
function footerajax(){
//same here
return $.post("templates/footer.php", { ... });
}
// chain the deferred calls :
contentajax()
.then( footerajax() )
.then( csschanges() )
If you also want to wait for the loading of the images to complete, you can still use this Deferred abstraction by wrapping the loading mechanism inside a single Promise. I googled around and found this gist (due credit should be given to the author : Adam Luikart).
Try to use callback function.
Instead of using .css try using .animation({'':''},200,function(){"........another function here......"})
Same with fadeOut as .fadeOut(200,function(){".....another function here........."})
So at the end you will only call contentajax().
Hope that helps.
By default your ajax calls are async. You can't guarantee the order of returns async. It sounds like you want execution in synchronous order. Either use
async: false
in your ajax calls, or use each next function as a success callback to the current one and don't loop through them in preload.
success: function(data, textStatus, jqXHR)
{
successCallback(successCallbackArgs);
}

Call a function everytime and AJAX request is processed and returned from the server

I have a application where there are numerous number of ajax calls to the server.
Now I want to audit the response that comes from the server (This requirement poped up after the ajax code was laid).
So I have a function that would audit the response data, only problem is how can I get the data to be sent to the function which now sits separately.
I don't want to do the laborious work of adding the line of code for calling the function in each ajax call.
Is there easier and general way out. Somehow I could detect when a response come back and then process the response.
Using both traditional javascript method as well as jquery ajax calls in the system. (The app has been getting changes from a long time and has changed hands a lot so the new things get added and the older ones never get removed)
Wrap your ajax calls with a helper function and use it throughout your code.
An (untested) example:
MyApp = MyApp || {
logRequest: function _logRequest(settings, response) {
// Log your response
},
ajax: function _ajax (settings) {
var that = this;
// Log attempt request here?
// Example of logging the success callback (do similar for error or complete)
if (settings.success) {
// A success handler is already specified
settings.success = function (data) {
that.logRequest(settings, data); // Log the response
settings.success(data); // Call the original complete handler
};
} else {
// No success handler is specified
settings.success = function (data) {
that.logRequest(settings, data);
};
}
return jQuery.ajax(settings);
}
};
I favour this mechanism for lots situations where I want to reduce boilerplate. I only have to modify the state of the MyApp object which is my own (named appropriately for the application), so it is sort of an interface that allows you to intercept function calls without modifying other global objects. You can also swap this functionality out with something else very easily without having to update your references everywhere, which could be useful in a lot of other situations as well.
Using .ajaxComplete() should be enough to catch the onComplete event for all AJAX requests made through jQuery. Isn´t that what you´re asking for?
$('.ajaxRequest').click(function(event) {
event.preventDefault();
$.getJSON(
'/echo/json/',
this.id,
function(data, textStatus, jqXHR) {
console.log(data, textStatus, jqXHR);
}
);
});
// Listen to all ajax requests
$("#log").ajaxComplete(function(event, request, settings) {
console.log(event, request, settings);
});​
View demo.

Callback in jQuery wrapper function

I have written a function that retrieves a html template, then binds data using jQuery.tmpl. I think it's fairly neat and tidy and encapsulates what I need and provides me a reusable function. My question however is can it be improved.
My main concern is what if the $.get method fails, and also how the callBack function is executed.
function Bind(templateURL, templateData, templateTarget, callBack){
var req = $.get(templateURL);
req.success(function(templateHtml) {
$(templateTarget).html(''); //clear
$(templateHtml).tmpl(templateData).appendTo(templateTarget); //add deal
callBack();
});
}
You can pass the result of tmpl() directly to html() to clear your target container and append the new content at the same time. You can also chain the result of $.get() into your success handler to avoid using a local variable:
function Bind(templateURL, templateData, templateTarget, callBack)
{
$.get(templateURL).success(function(templateHtml) {
$(templateTarget).html($(templateHtml).tmpl(templateData));
callBack();
});
}
If $.get() fails, nothing will happen since you do not register an error handler. What that handler would do is up to you, but you might want to display an appropriate message in an alert box or somewhere on the page.
Your second concern is less clear. As it stands, callBack will only be called on success, and without arguments.
You can use $.ajax to assign and error calback. ex:
var jqxhr = $.ajax({ url: "example.php" })
.success(function() { alert("success"); })
.error(function() { alert("error"); })
Check the api http://api.jquery.com/jQuery.ajax/

Categories