Reputation: 24579
I'm trying to figure out how I can reset a timer created inside of an immediately invoking function from within the setTimeout closure. Here is my function:
var triggerHeightRecalc = function() {
setTimeout(function() {
if(imagesLoaded()) {
adjustHeight();
} else {
triggerHeightRecalc();
}
}, 100);
}();
In the event that imagesLoaded()
returns false, I receive the following error from attempting to call triggerHeightRecalc()
:
Uncaught TypeError: undefined is not a function
So I'm not sure if the issue is the function is not in the scope, or maybe it just cannot call itself? I've tried passing triggerHeightRecalc
as a parameter in the setTimeout
closure, but that doesn't seem to work either.
I've also tried this after reading this SO question:
var triggerHeightRecalc = function() {
var that = this;
var callback = function() {
if(imagesLoaded()) {
adjustHeight();
} else {
that.triggerHeightRecalc();
}
};
timeDelay = window.setTimeout(callback, 100);
}();
What am I doing wrong here, or is there a better way? Is this something that should be a setInterval()
instead and I clear the interval when images are loaded?
Side Note: I'm calculating the height of a div inside a jQuery plugin, but I need to wait until the images are loaded in order to get the correct height (not sure if that is relevant).
Upvotes: 0
Views: 147
Reputation: 7975
Patrick Evans has the right reasons, but there is a neater way to solve it :)
(function triggerHeightRecalc() {
setTimeout(function() {
if(imagesLoaded()) {
adjustHeight();
} else {
triggerHeightRecalc();
}
}, 100);
})();
Here you are give an internal name to the (still) anonymous function. The name is only visible from within the function itself, its not visible in the global scope. Its called a Named function expression.
Upvotes: 0
Reputation: 3007
Already answered, but I'll put this in.
First of all, if you just want to wait until all images have loaded you can use: https://github.com/desandro/imagesloaded and then run the above code.
If that's not what you want, and you you just want a function that your setTimeout
can run, then you can remove the ()
at the end of the function.
Here is what's happening in your current code
Your function is missing the opening bracket or similar character !+(
(function
.
Also your IIFE has no return
keyword, and will return undefined
to triggerHeightCalc.
If you do want an IIFE then you can either have a private version that is only callable within itself.
(function myModule(){
myModule(); //calls itself
})();
Or a public version that can be called both inside and outside.
var myModule = (function(){
return function myMod(){
myMod();
}
})();
myModule();
Upvotes: 1
Reputation: 42736
Since you are invoking the function right from the declaration triggerHeightRecalc
is getting set to the return of that function call, which is undefined
since you in fact do not return anything.
You can do two things
1. Declare then invoke
var triggerHeightRecalc = function() {
setTimeout(function() {
if(imagesLoaded()) {
adjustHeight();
} else {
triggerHeightRecalc();
}
}, 100);
};
triggerHeightRecalc();
2. Wrap the declaration in ()
and invoke
var triggerHeightRecalc;
(triggerHeightRecalc = function() {
setTimeout(function() {
if(imagesLoaded()) {
adjustHeight();
} else {
triggerHeightRecalc();
}
}, 100);
})();
The second one will create a global variable unless you do the var triggerHeightRecalc;
before hand.
Upvotes: 2