1

I am trying to understand callbacks via setTimeout function. I have two sets of code :

for (var i = 1; i <= 10; i++) {
        (function(callback,i){
          setTimeout(function(){
            callback(i)
          }, 0);
         })(function(val){console.log(val)},i);

It works fine printing 1,2,3,.... 10

But when i am trying to abstract setTimeout's callback function as :

for (var i = 1; i <= 10; i++) {
        (function(callback,i){
          setTimeout(func, 0);
         })(function(val){console.log(val)},i);
        }
function func(){
    callback(i)
  }

It gives me error stating

Uncaught ReferenceError: callback is not defined

I know there is some issue with lexical scoping of declaration of that func function. But not able to comprehend the reason. Please do help me understand this.

Gyanesh Gouraw
  • 1,991
  • 4
  • 23
  • 31

3 Answers3

2

callback is not defined within func . You can pass func as parameter to IIFE, use Function.prototype.bind() to pass i to callback : func

for (var i = 1; i <= 10; i++) {
  (function(callback, i) {
    setTimeout(callback.bind(null, i), 0);
  })(func, i);
}

function func(val) {
  console.log(val)
}
guest271314
  • 1
  • 15
  • 104
  • 177
  • 1
    Your answer is very similar to the solution which OP is having. He used an anonymous function and you used bind. Both are same. But OP is asking why his second snippet is not working. What is the purpose of `func` in your code? – Rajaprabhu Aravindasamy Mar 12 '16 at 06:38
  • _"But OP is asking why his second snippet is not working. What is the purpose of func in your code?"_ `func` is passed as parameter to IIFE, which is referenced as `callback` within IIFE. `.bind()` does not call `func` : `callback`, but passes reference of `func` : `callback` to `setTimeout` with `i` as parameter. Have you tried your posted solution ? , appears to log `11` to `console` ten times ? – guest271314 Mar 12 '16 at 06:43
  • I didn't notice that my code was printing 11 ten times. THanks for pointing it. – Rajaprabhu Aravindasamy Mar 12 '16 at 06:48
2

It is throwing reference error because, the function func it has a scope where there is no declaration for callback. You can fix it by passing the callback as a parameter to func.

for (var i = 1; i <= 10; i++) {
  (function(callback, i) {
    setTimeout(func, 0, callback.bind(null, i)); //Pass the callback here as a parameter to func. 
                                   //(setTimeout can pass its >2 parameter as 
                                   //its callback parameter)
  })(function(val) {
    console.log(val)
  }, i);
}

function func(callback) { //receive the callback here and use it.
  callback();
}
Rajaprabhu Aravindasamy
  • 66,513
  • 17
  • 101
  • 130
1

In func you don't have reference to callback that you declared in your IIFE.So,it start looking in current scope which is your func scope.then it try to find in global scope,it also not defined there.Finally it throws an error

You need to pass the refarence to this callback parateter refering the function to get rid of this error.

for (var i = 1; i <= 10; i++) {
        (function(callback,i){
          setTimeout(func.bind(null,callback,i), 0);
         })(function(val){console.log(val)},i);
        }
function func(callback,i){
    callback(i)
  }
RIYAJ KHAN
  • 15,032
  • 5
  • 31
  • 53