Javascript breaking a for loop inside a callback function

て烟熏妆下的殇ゞ 提交于 2019-11-27 09:06:15
penartur

If your code sample does represent some actual code (i.e. all the processing is done in the same event loop tick), you may do the following:

function test(obj) {

    if (some_condition) {
        return obj.onload();
    } else {
        return obj.onerror();
    }
}

var result;
for(var i=0; i<4; i++){   

    result = test({
        onload:function(e){          
            //some code to run
            return true;
        },
        onerror:function(e){
            return false;
        }


    });

    if (!result) {
        break;
    }
}

Otherwise, if there is something asynchronous done, you have to call test sequentially, and not in parallel. For example,

function test(obj) {
    doSomeAjaxRequest(arguments, function (err, result) {
        if (some_condition) {
            obj.onload();
        } else {
            obj.onerror();
        }
    });
}

var f = function (i) {
    if (i >= 4) return;
    test({
        onload:function(e){          
            //some code to run
            f(i+1);
        },
        onerror:function(e){
            break;
        }
    });
}

f(0);

Not possible. A for loop is a synchronous procedure while an Ajax request is not. That means when the onerror callback happens, the for loop is already done executing.

As an alternative you could introduce a check into your onsuccess handler which confirms no errors have happened yet.

var errorOccured = false;
for(var i=0;i<4;i++){   

test({
    onload:function(e){   
        if(errorOccured) return;
        //some code to run
    },
    onerror:function(e){
        errorOccured = true;
    }


});
}

Bit hacky maybe but one could do something like this with a handler function.

var handler = function(array, callback){
    for(var i=0, l=array.length, e=array[i]; i<l; ++i){
        if(true === handler.exit){
            handler.exit = false; //restore
            return;
        }
        callback.call(null, e);
    }
};
handler.exit = false; 

handler([1,2,3], function(e){
   console.log(e);
   if(2 === e){
       arguments.callee.caller.exit = true; // :-)
   }
});

Didn't test this but maybe you could bind function to scope in call even?

var handler = function(a, f){
    this.exit = false;
    for(var i=0, l=a.length, e=a[i]; i<l; ++i){
        if(true === this.exit){
            this.exit = false; //restore
            return;
        }
        callback.call(this, e);
    }
};
handler([1,2,3], function(e){
   console.log(e);
   if(2 === e){
       this.exit = true;
   }
});

You cannot break the loop inside test() function. I think the best solution in this case would be to throw an exception inside test() function, then catch it in the loop and break.

Maybe you can make the 'onload' callback recursive?

Meaning, you just call the 'test' method inside the 'onload' handlerr, this would also mean you fire all requests in order instead of all at the same time.

I take the answer of penartur, but I modified without the "break":

function test(obj) {
    doSomeAjaxRequest(arguments, function (err, result) {
        if (some_condition) {
            obj.onload();
        } else {
            obj.onerror();
        }
    });
}

var f = function (i) {
    if (i >= 4) return;
    test({
        onload:function(e){          
            //some code to run
            f(i+1);
        },
        onerror:function(e){
            console.log('stop');
        }
    });
}

f(0);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!