A public method wants to call a private method (passing some objects as arguments) after some period of time... How do we do it?
Wanted something like this:
var someClass = function(someObj) {
var myPrivateMethod = function(someParam) {
alert('i got ' + someObj + '!');
if (someParam) alert('and i also got ' + someParam + '!');
}
var myDearPublicMethod = function(someParam) {
if (someParam) {
//call myPrivateMethod with setTimeOut so that it gets the someObj (and someParam if provided)
} else {
myPrivateMethod(someParam);
}
}
return {
somePublicMethod : myDearPublicMethod
}
}
someClass('something').somePublicMethod('somethingELSE');
Call an anonymous function that calls the function:
window.setTimeout(function(){
localFunction(someObject);
}, 1000);
it's not clear what is your goal
if (someParam) {
//call myPrivateMethod with setTimeOut so that it gets both someObj and someParam
} else {
myPrivateMethod(someParam);
}
why in the else branch you call a method with someParam as a parameter if in that branch you just verified that someParam is false, null or undefined? what the real difference between branches?
Related
This is probably basic... given a fully qualified function name, I'm trying to call it via .apply()
Superficial example
var ns = {
someFunc: function() { console.log('stuff'); }
}
function someTopLevelFunc() { console.log('top level'); }
Given a method that takes the name of that function, us there some way to call the namespaced function?
function theCaller(funcName) {
console.log("Callback name: " + callbackFunctionName)
const callbackFunction = window[callbackFunctionName];
console.log("Type: " + (typeof callbackFunction))
if((typeof callbackFunction) === "function") {
callbackFunction.apply(null, []);
}
}
theCaller('topLevelFunc');
theCaller('ns.someFunc');
The first call works while the second call shows the callbackFunction type as undefined
Probably a simple syntax issue, but my googling has failed me.
How would I go about detecting recurring methods and grouping them by an identifier when calls to the recurring methods are asynchronous?
To demonstrate the use of time taken before the callback is called, setTimeout is being used.
var counter = 0
var foo = (function () {
var context
return function foo (callback) {
if (!context) {
context = {id: ++counter}
}
setTimeout(function () {
callback.call(context)
context = null
}, 1)
}
}())
foo(function () {
console.log(1, this.id)
foo(function () {
console.log(2, this.id)
})
})
foo(function () {
console.log(3, this.id)
})
The above code produces:
1 1
3 undefined
2 undefined
The desired result is:
1 1
3 2
2 1
Ideally, this would be achieved without having to use anything like .bind on the foo calls.
I've experimented briefly with arguments (more specifically arguments.callee) and am aware I most likely need some way of duplicating foo with different ids, though I couldn't get any results which persisted the id on the arguments.callee function returned.
EDIT: Thanks for the answers so far! These are perfect answers for the question, but my use case does take a step further.
In the current scenario, the callback may be called asynchronously at an indeterminate time, meaning context slides back to null before I need it to.
I've edited the above code and explanation to reflect that new issue.
You could create a variable in a closure around the foo method that stores if the method is currently "being called". It's hard to explain, but this is what it would look like:
var foo = (function() {
var locked;
return function (callback) {
if (!locked) {
counter += 1;
this.id = counter;
}
locked = true;
// Any time this callback calls 'foo',
// it will see it is locked and not increase the id
callback();
locked = false;
}
}());
var counter = 0;
var foo = (function() {
var locked;
return function(callback) {
if (!locked) {
counter += 1;
this.id = counter;
}
locked = true;
// Any time this callback calls 'foo',
// it will see it is locked and not increase the id
callback();
locked = false;
}
}());
foo(function() {
log([1, this.id])
foo(function() {
log([2, this.id])
})
})
foo(function() {
log([3, this.id])
})
function log(msgs) {
document.body.insertAdjacentHTML("beforeend", "<code>" + msgs.join(" ") + "</code><br />"); }
Is it possible to pass a callback function that does not exist yet? My goal is to have a common function that will wait for another callback function to exist, when it does exist, it should execute it. This is what I have so far, but I can't figure out how to pass the function in that doesn't exist as a function yet.
function RunTemplateFunction(callback, userInfo) {
if ($.isFunction(callback)) {
callback(userInfo);
} else {
var myInterval = setInterval(function () {
if ($.isFunction(callback)) {
clearInterval(myInterval);
callback(userInfo);
}
}, 200);
}
}
I run the function like this:
RunTemplateFunction(MyFunctionToRun, GetUserInfo());
I get MyFunctionToRun is undefined for obvious reasons, I also tried the workaround of passing the function as a string and then convert the string to a function using eval(). But that throws the same error. I also thought of using the new function(), but that actually creates a new function.
Any help is appreciated. thank you.
If you call RunTemplateFunction by undefined there is no way we can see, is callback is defined or not, as we don't have reference to anything.
If you can modify the declaration to accept object as below, we can achieve what we want
function RunTemplateFunction(options, userInfo) {
if ($.isFunction(options.callback)) {
console.log('called1',userInfo);
options.callback(userInfo);
} else {
var myInterval = setInterval(function () {
if ($.isFunction(options.callback)) {
console.log('Called dynamically!!');
clearInterval(myInterval);
options.callback(userInfo);
}
}, 200);
}
}
var options = {}
RunTemplateFunction(options,{user:122});
options.callback = function(){
console.log("I'm called!!");
}
This will print
Called dynamically!!
I'm called!!
EDIT:
We can also call callback function in following way without setInterval, it will look different but options.callback variable is replaced by template.callMe function and its instantaneous also.
function TemplateRunner(userInfo){
this.callMe = function(cb){
this.templateFunction(cb);
}
this.templateFunction = function(callback){
callback(userInfo);
}
}
var template = new TemplateRunner({user:100})
template.callMe(function(user){
console.log('call me1',user);
});
template.callMe(function(user){
console.log('call me2',user);
})
This will print
call me1 {user: 100}
call me2 {user: 100}
I've written a function which may take an unknown number of functions as parameters, but can't figure how I can make this work when one or more of the functions take parameters too.
Here is a quick example of what I would like to achieve:
function talk(name) {
console.log('My name is ' + name);
var callbacks = [].slice.call(arguments, 1);
callbacks.forEach(function(callback) {
callback();
});
}
function hello() {
console.log('Hello guys');
}
function weather(meteo) {
console.log('The weather is ' + meteo);
}
function goodbye() {
console.log('Goodbye');
}
// I would like to be able to do the following:
//talk('John', hello, weather('sunny'), goodbye);
You can pass an anonymous function which can call the function with required parameters
talk('John', hello, function(){
weather('sunny')
}, goodbye);
function talk(name) {
console.log('My name is ' + name);
var callbacks = [].slice.call(arguments, 1);
callbacks.forEach(function(callback) {
callback();
});
}
function hello() {
console.log('Hello guys');
}
function weather(meteo) {
console.log('The weather is ' + meteo);
}
function goodbye() {
console.log('Goodbye');
}
talk('John', hello, function() {
weather('sunny')
}, goodbye);
talk('John', hello, weather.bind(null, 'sunny'), goodbye);
In this case .bind is essentially returning a function with some bound parameters - quite analogous to Arun's answer, though you may consider this method a little more succinct / readable.
Creating the closure is easy but using it is confusing for me. Here is my closure. Once I have it I need to be able to call operations on it like doWork, calculateThis, doAnimation, etc. but there doesn't seem to be a way to access functions inside the closure.
function worker(input) {
return function () {
doWork = function () {
alert("doing work");
};
}
}
function caller() {
var myWorker = worker();
myWorker.doWork(); // this fails
}
*The question you're asking appears subjective and is likely to be closed. - Thanks again stackoverflow
I believe this is what you are asking for:
function worker(input) {
return {
doWork: function () {
alert("doing work");
},
doAnimation: function() {
alert("animating");
}
}
}
You can now call it using your code:
var myWorker = worker();
myWorker.doWork();
myWorker.doAnimation();
Note that your code is not really using closures, but this one does:
function worker(input) {
return {
doWork: function () {
alert("doing work: " + input);
},
doAnimation: function() {
alert("animating: " + input);
}
}
}
var workerA = worker('A');
var workerB = worker('B');
workerA.doWork();
workerB.doAnimation();
Can you see the difference?
You are trying to execute a method work() but in your example you return a function, not an object with a property "work".
Here's what you're probably after:
function worker(input) {
return {
work: function () {
alert("doing work");
};
}
}