Can additional functionality be binded to a function? - javascript

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");

Related

self-executing anonymous functions and call it again

I want to do something like this:
var build= (function(){
//my function body
})();
function test(){
//somthing then call build
build() //i want to call build function again in my code
}
How can I do this?
I tried this in angular:
var buildRoot = (() => {
$SubNode.get({
TypeID: vendorAdminService.NodeType.Category
}, function(data: vendorAdminService.IGetNodeParameters) {
$scope.ProductTree = data.TreeNodeModelItem;
$scope.AjaxLoading = false;
}, function(err) {
// alert(err)
})
})();
$mdDialog.show(confirm).then(function() {
$Category.Remove(node.ID)
buildRoot
}, function() {
});
but it does not work.
Anybody can guide me??
You need to return a function in your IIFE.
If you IIF is not trivial and has many functionalities you could also consider using Reveal Module Pattern.
var build = (function() {
var f = function() {
console.log('hello');
};
f();
return f;
})();
function test() {
build();
}
test();
Just use a named function.
Your IIFE needs to return a function, for later calling. But then is no need for an anonymous function.
function build() {
//my function body
}
or
var build = function () {
//my function body
};
var build = (function() {
var init = function() {
// magic code
};
return {
init: init
}
}());
function test() {
build.init()
}
test();
You include all your functionalities inside your build object, and you'll be able to call them as soon as you return them from inside that object. This effectively is called the revealing module pattern
For more information, read this
I see that there are missing semi-colons ";"
$mdDialog.show(confirm).then(function() {
$Category.Remove(node.ID);
buildRoot();
}, function() {
});

Make a function that can perform multiple callback with one parameter

I'm working on a big project and I simplified what it matters here. This is the code:
a = new Thing(/*sayHi + sayHey*/);
function sayHi() {
alert("hi");
}
function sayHey() {
alert("hey");
}
function Thing (callback) {
callback();
}
I'd like to, with just the callback parameter, call both the sayHi() and the sayHey() function, at the order I put them. Is it possible? How would I do it? Thank you.
Pass an anonymous function that calls both of them sequentially:
a = new Thing(function() {
sayHi();
sayHey();
});
function sayHi() {
alert("hi");
}
function sayHey() {
alert("hey");
}
function Thing (callback) {
callback();
}
Alternatively to #Barnar's answer, create and pass a regular named function. If the callback logic gets heavier, you might want that anyway.
function hiHeyCallback() {
sayHi();
sayHey();
}
a = new Thing(hiHeyCallback);

Run a function after an on.change event

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

jQuery/JavaScript - Start one function once another has finished?

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())();
}

js execute function after object is defined

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.

Categories