I have something like this: $('#select1').on('change', function() {}) and it works fine. However, I need to run another function after the function has completed.
I thought about taking the function contents, and putting it in a named function, then taking the second function and doing the same, and placing them in the anonymous function:
$('#select1').on('change', function() {
function1 ();
function2 ();
});
However, I was hoping there was another way. The above seems inconsistent with jQuery.
Though you could nest functions with callbacks, generally the best practice in jQuery is to use jQuery.Deferred.
var function1 = function() {
var deferred = $.Deferred();
//Do your thing. When finished, call deferred.resolve()
return deferred;
}
var function2 = function() {
//Function 2 code
}
$('#select1').on('change', function() {
function1().then(function2);
});
why dont you try jquery change function insted javascript bind
$( "#select1" ).change(function() {
function1();
function2()
});
Try this:
$('#select1').on('change', function() {
function1(someVariable, function() {
function2(someOtherVariable);
});
});
function function1(param, callback) {
//...do stuff
callback();
}
Here is where I found that:
Call a function after previous function is complete
Related
I'm tryng to do some jQuery stuff when both instagramLoadError and imagesLoaded functions have been loaded.
For this I'm using if(instagramLoadError() && imagesLoaded()){}) but it's not working as expected.
I'm just starting with JS but I read something about "scope" saying that I can't target my instagramLoadError and imagesLoaded functions since it's not within the same scope. For this reason or another I'm still getting the "x function is not defined" error.
What should I do in this case?
$(document).ready(function(){
(function(){
new InstagramFeed({
'on_error': function instagramLoadError(){
return true;
}
});
})();
});
$(document).ready(function(){
$('#myDiv').imagesLoaded(function(){
return true;
});
});
$(document).ready(function(){
if(instagramLoadError() && imagesLoaded()){
// do some stuff if both instagramLoadError and imagesLoaded functions have been executed
}
});
Try like this:
$(document).ready(function() {
var isInstagramLoadError = false;
var isImagesLoaded = false;
(function() {
new InstagramFeed({
'on_error': function() {
isInstagramLoadError = true;
checkBoth();
}
});
})();
$('#myDiv').imagesLoaded(function() {
isImagesLoaded = true;
checkBoth();
});
function checkBoth() {
if (isInstagramLoadError && isImagesLoaded) {
// do some stuff if both instagramLoadError and imagesLoaded functions have been executed
};
};
});
The issue is that you are dealing with asynchronous callback functions. Each function will run when something happens (Instagram load error or images loaded) and the order of the two cannot be guaranteed. So to deal with this, have each function update a variable and then call a common function checkBoth() to check the variables.
you can use Promise.all method. which will wait for all promise to complete
$(document).ready(function(){
function Instagram(){
new InstagramFeed({
'on_error': function instagramLoadError(){
return true;
}
function images(){
$('#myDiv').imagesLoaded(function(){
return true;
}
Promise.all([Instagram(),images()]).then(res=>{
if(res[0] && res[1]){
// do some code
}
})
})
Promise. all will wait for functions to complete and store the data returning in an array.
What is the best way to fire a function once another has finished?
At the moment I have 6 functions that I'm calling on DOM load like this:
$(document).ready(function(){
func1();
func2();
func3();
func4();
func5();
func6();
});
function func1(){
do some stuff
}
function func2(){
do some stuff
}
function func3(){
do some stuff
}
function func4(){
do some stuff
}
function func5(){
do some stuff
}
function func6(){
do some stuff
}
But I want them to fire one after another. How would I do this?
Thanks in advance
Try by using callbacks like,
$(document).ready(function(){
func1(func2);
});
function func1(callback){
do some stuff
callback('func2');
}
function func2(callback){
do some stuff
callback('func3');
}
function func3(callback){
do some stuff
callback('func4');
}
function func4(callback){
do some stuff
callback('func5');
}
function func5(callback){
do some stuff
callback('func6');
}
function func6(callback){
do some stuff
}
Read callback-functions-javascript
You can refer Is there a better way to do callback chaining in javascript? for chained callbacks
function func1(){
do some stuff
_next();
}
function func2(){
do some stuff
_next();
}
function func3(){
do some stuff
_next();
}
function func4(){
do some stuff
_next();
}
function func5(){
do some stuff
_next();
}
function func6(){
do some stuff
_next();
}
function chainCallbacks() {
var _this = this;
var _counter = 0;
var _callbacks = arguments;
var _next = function() {
_counter++;
if(_counter < _callbacks.length) {
_callbacks[_counter].apply(_this);
}
};
_this._next = _next;
return function() {
if(_callbacks.length > 0) {
_callbacks[0].apply(_this);
}
};
}
var queue = chainCallbacks(func1, func2, func3,func4,func5,func6);
queue();
The way you wrote it is correct for synchronous code. However, based on your comment it sounds like you are firing off external requests that run asynchronously. What happens in this case is that function1 may fire off some code accessing Sharepoint and then will complete the rest of the code in function 1 after that...and then flow right into function2 without waiting to see what happens with the Sharepoint request.
My preferred way of dealing with this would be using callbacks from the asynchronous operations. Once you pull that data from Sharepoint, for instance, you are going to call some other function (we'll call it Sharepoint_callback1). Add a call to that function:
$(document).ready(function(){
func1();
});
function func1(){
do some stuff that calls Sharepoint, which after complete calls Sharepoint_callback1
}
function func2(){
do some stuff
}
function Sharepoint_callback1() {
do some stuff
func2();
}
There are other methods of doing this. JQuery provides callback handlers for almost of its operations, but it all essentially boils down to the same thing as above.
If I misunderstood the question I apologize; please post additional details and I'll modify my answer.
You could write a queue function. For queue of functions you can use array:
var fn1 = function() {},
fn2 = function() {},
MyQ = [];
//add functions to array
MyQ.push(fn1);
MyQ.push(fn2);
//remove and call the first item of an array
(MyQ.shift())();
If you want use your function with scope and arguments, you can wrap functions, for example:
MyFnWithParam = function(fn, scope, params){
scope = scope || window;
params = params || [];
return function() {fn.apply(scope, params)};
};
var fn1 = MyFnWithParam(fn, this, params),
fn2 = MyFnWithParam(fn, this, params),
MyQ = [];
MyQ.push(fn1);
MyQ.push(fn2);
while (MyQ.length > 0) {
(MyQ.shift())();
}
I need for a function to be executable only after an object is defined, I'm currently working in a fascade pattern and one method is dependent on another method. in this case 'addNewLayer' fails because 'setFullMap' hasn't finished executing. is there a solution? I'm using jquery and vanilla js so most any solution would be helpful at this point:
var jen = (function(){
function setFullMap(mapID){
jen.map = new Map(mapID);
}
function setLayer(opt){
//execute code here after jen.map is defined
}
return{
samp: function(id, opt){
setFullMap(id);
addNewLayer(opt);
}
};
})();
Thanks
solution:
var jen = (function(){
function setFullMap(mapID, callback) {
jen.map = new Map(mapID);
if(jen.map){
callback();
}
}
return {
samp: function(id, opt){
setFullMap(id, function(){
addNewLayer(opt);
}.bind(this));
}
};
})();
You will have to pass a callback function to setFullMap, and execute it once the function has completed (at the very end, before the closing }).
var jen = (function(){
function setFullMap(mapID, callback){
jen.map = new Map(mapID);
callback();
}
function setLayer(opt){
//execute code here after jen.map is defined
}
return{
samp: function(id, opt){
setFullMap(id, function() {
addNewLayer(opt);
}.bind(this));
}
};
})();
Do not forget using .bind(this) - it is very important in order to keep the original this in your callback function.
Edit:
Actually that would not work work if the Map constructor is a-synchronous. If you do not have access to the constructor and/or you cannot pass it a callback, then presumably the only (and sad) option would be to use a setTimeout or (easier) setInterval, continuously checking at defined intervals if the operation has been completed, and then fire the callback.
You could use a callback parameter:
function setFullmap(mapId,callback) {
jen.map = new Map(mapId);
callback();
}
....
samp: function(id, opt){
setFullMap(id,function() {
addNewLayer(opt);
});
}
When u dont have a way to manipulate the Map Object then u need to use a loop:
var loop=self.setInterval(function(){
if(jen.map) {
//execute code here after jen.map is defined
console.log(typeof jen.map);
window.clearInterval(loop);
}
},50);
Check jsfiddle:
http://jsfiddle.net/9yv5t/1/
I have checked the docs and it seems that there are various events you could listen to.
For example:
var m = new Map(...);
m.on('load', function () {
//execute code when the first layer is ready
});
var l = new Layer(...);
l.on('load', function () {
//execute code when the layer has been initialized
});
It's also carefully stated for the Layer.load event:
fires after layer properties for the layer are successfully populated.
This event must be successful before the layer can be added to the
map.
If I have a function like this:
function showAlert() {
alert("1");
}
Is there a way to bind additional functionality to the same function in a different part of the page?
Like this:
function showAlert() {
alert("1");
alert("2");
}
You can overwrite the function with a new function that calls the old function.
function showAlert() {
alert("1");
}
showAlert = (function (original){
return function () {
original();
alert("2");
}
}(showAlert));
showAlert();
Well, you can simply redefine the function:
function showAlert() {
alert("1");
}
var originalShowAlert = showAlert;
showAlert = function(){
originalShowAlert();
alert("2");
}
showAlert();
Since functions are treated simply as objects in JS, you can maintain an array of functions, then execute each function in a loop. This allows you to add any type of function that you want to the collection (and even remove them later if you keep the index), without breaking the execution train.
var funk = [];
funk.push(function showAlert1()
{
alert("1");
});
funk.push(function showAlert2()
{
alert("2");
});
funk.push(function showAlertFromMsg()
{
alert("You passed " + this);
});
for(var i=0,len=funk.length; i<len; i++) funk[i].call("This is my message");
I have the following JavaScript code:
$('a.button').click(function(){
if (condition == 'true'){
function1(someVariable);
function2(someOtherVariable);
}
else {
doThis(someVariable);
}
});
How can I ensure that function2 is called only after function1 has completed?
Specify an anonymous callback, and make function1 accept it:
$('a.button').click(function(){
if (condition == 'true'){
function1(someVariable, function() {
function2(someOtherVariable);
});
}
else {
doThis(someVariable);
}
});
function function1(param, callback) {
...do stuff
callback();
}
If you're using jQuery 1.5 you can use the new Deferreds pattern:
$('a.button').click(function(){
if(condition == 'true'){
$.when(function1()).then(function2());
}
else {
doThis(someVariable);
}
});
Edit: Updated blog link:
Rebecca Murphy had a great write-up on this here: http://rmurphey.com/blog/2010/12/25/deferreds-coming-to-jquery/
Try this :
function method1(){
// some code
}
function method2(){
// some code
}
$.ajax({
url:method1(),
success:function(){
method2();
}
})
This answer uses promises, a JavaScript feature of the ECMAScript 6 standard. If your target platform does not support promises, polyfill it with PromiseJs.
Promises are a new (and a lot better) way to handle asynchronous operations in JavaScript:
$('a.button').click(function(){
if (condition == 'true'){
function1(someVariable).then(function() {
//this function is executed after function1
function2(someOtherVariable);
});
}
else {
doThis(someVariable);
}
});
function function1(param, callback) {
return new Promise(function (fulfill, reject){
//do stuff
fulfill(result); //if the action succeeded
reject(error); //if the action did not succeed
});
}
This may seem like a significant overhead for this simple example, but for more complex code it is far better than using callbacks. You can easily chain multiple asynchronous calls using multiple then statements:
function1(someVariable).then(function() {
function2(someOtherVariable);
}).then(function() {
function3();
});
You can also wrap jQuery deferrds easily (which are returned from $.ajax calls):
Promise.resolve($.ajax(...params...)).then(function(result) {
//whatever you want to do after the request
});
As #charlietfl noted, the jqXHR object returned by $.ajax() implements the Promise interface. So it is not actually necessary to wrap it in a Promise, it can be used directly:
$.ajax(...params...).then(function(result) {
//whatever you want to do after the request
});
Or you can trigger a custom event when one function completes, then bind it to the document:
function a() {
// first function code here
$(document).trigger('function_a_complete');
}
function b() {
// second function code here
}
$(document).bind('function_a_complete', b);
Using this method, function 'b' can only execute AFTER function 'a', as the trigger only exists when function a is finished executing.
you can do it like this
$.when(funtion1()).then(function(){
funtion2();
})
This depends on what function1 is doing.
If function1 is doing some simple synchrounous javascript, like updating a div value or something, then function2 will fire after function1 has completed.
If function1 is making an asynchronous call, such as an AJAX call, you will need to create a "callback" method (most ajax API's have a callback function parameter). Then call function2 in the callback. eg:
function1()
{
new AjaxCall(ajaxOptions, MyCallback);
}
function MyCallback(result)
{
function2(result);
}
If method 1 has to be executed after method 2, 3, 4. The following code snippet can be the solution for this using Deferred object in JavaScript.
function method1(){
var dfd = new $.Deferred();
setTimeout(function(){
console.log("Inside Method - 1");
method2(dfd);
}, 5000);
return dfd.promise();
}
function method2(dfd){
setTimeout(function(){
console.log("Inside Method - 2");
method3(dfd);
}, 3000);
}
function method3(dfd){
setTimeout(function(){
console.log("Inside Method - 3");
dfd.resolve();
}, 3000);
}
function method4(){
console.log("Inside Method - 4");
}
var call = method1();
$.when(call).then(function(cb){
method4();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
If function1 is some sync function that you want to turn into an async one because it takes some time to complete, and you have no control over it to add a callback :
function function1 (someVariable) {
var date = Date.now ();
while (Date.now () - date < 2000); // function1 takes some time to complete
console.log (someVariable);
}
function function2 (someVariable) {
console.log (someVariable);
}
function onClick () {
window.setTimeout (() => { function1 ("This is function1"); }, 0);
window.setTimeout (() => { function2 ("This is function2"); }, 0);
console.log ("Click handled"); // To show that the function will return before both functions are executed
}
onClick ();
The output will be :
Click handled
...and after 2 seconds :
This is function 1
This is function 2
This works because calling window.setTimeout () will add a task to the JS runtine task loop, which is what an async call makes, and because the basic principle of "run-to-completion" of the JS runtime ensures that onClick () is never interrupted before it ends.
Notice that this as funny as it makes the code difficult to understand...