Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript: is there any better way to do a for loop with callback function?

for(var i=1; i<496; i++) {
    (function(num) {
        myApp.getTerm(num, function (term, def){
            myApp.quizlet[0].terms[num] = { term: term, definition: def};
        });         
    })(i);
};

I'm calling a function with callback inside a for-loop. The callback function need to access the current loop's iteration i. I'm coming up with the solution above.

Is there any other way to do things like this?

like image 393
JackSMTV Avatar asked May 07 '26 14:05

JackSMTV


2 Answers

It's more readable to define a named function to call:

myApp.getTermForQuizzlet = function(num){
    myApp.getTerm(num, function (term, def){
        myApp.quizlet[0].terms[num] = { term: term, definition: def };
    });         
};

for(var i=1; i<496; i++) {
    myApp.getTermForQuizzlet(i);
};

Other than that, I don't know what you can do.

like image 124
mVChr Avatar answered May 10 '26 02:05

mVChr


What you're doing is not unreasonable and should work fine. Purely at the level of readability, I might go with

for(var i=1; i<496; i++) {
    function get_callback(n) {
        return function(term, def) {
            myApp.quizlet[0].terms[n] = { term: term, definition: def};
         };
    }
    myApp.getTerm(i, get_callback(i));         
};

If you are comfortable using Function.bind:

function callback (n, term, def) {
    myApp.quizlet[0].terms[n] = { term: term, definition: def};
}
for(var i=1; i<496; i++) {
    myApp.getTerm(i, callback.bind(this,i));
}

We bind the first argument to i, resulting in a "curried" function taking the term and def arguments.

Then of course there is this horrible hack, do not try this at home.

for(var i=1; i<496; i++) {
    try { throw i; }
    catch (i) {
        myApp.getTerm(i, function (term,def) {
             myApp.quizlet[0].terms[i] = { term: term, definition: def};
        });
    }
}