13

我有如下代码:

function test(obj) {

    if(//some conditon) {
        obj.onload();
    }else{
        obj.onerror();
    }
}


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

    test({
        onload:function(e){          
            //some code to run
        },
        onerror:function(e){
            break;
        }


    });
}

要点是 test() 函数是一个发出 XHR 请求的函数(它实际上是 Appcelerator Titanium 平台的一个 API,所以我无法控制它),我正在循环一些东西来调用测试函数。我需要在 onerror 函数上中断循环,但我收到一条错误消息,指出中断不在循环或 switch 语句内。我该如何重写这个?

4

6 回答 6

14

如果您的代码示例确实代表了一些实际代码(即所有处理都在同一个事件循环滴答中完成),您可以执行以下操作:

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;
    }
}

否则,如果有异步操作,您必须test按顺序调用,而不是并行调用。例如,

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);
于 2012-08-07T09:19:38.420 回答
3

不可能。for 循环是一个同步过程,而 Ajax 请求则不是。这意味着当 onerror 回调发生时,for 循环已经执行完毕

作为替代方案,您可以在 onsuccess 处理程序中引入检查,以确认尚未发生错误。

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;
    }


});
}
于 2012-08-07T09:16:17.830 回答
3

可能有点老套,但可以用处理函数做这样的事情。

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; // :-)
   }
});

没有对此进行测试,但也许您甚至可以将函数绑定到调用范围?

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;
   }
});
于 2012-10-23T12:11:21.737 回答
0

您不能打破 test() 函数内的循环。我认为在这种情况下最好的解决方案是在 test() 函数中抛出一个异常,然后在循环中捕获它并中断。

于 2012-08-07T09:16:17.440 回答
0

也许您可以使“onload”回调递归?

这意味着,您只需在“onload”处理程序中调用“test”方法,这也意味着您按顺序触发所有请求,而不是同时触发所有请求。

于 2012-08-07T09:24:26.807 回答
0

我接受 penartur 的回答,但我修改时没有“中断”:

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);
于 2017-10-28T22:00:16.697 回答