2012-08-07 6 views
9

tengo código como el siguiente:Javascript romper un bucle dentro de una función de devolución de llamada

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


    }); 
} 

Lo esencial es la prueba() es una función para hacer una solicitud XHR (en realidad es una API de la La plataforma Appcelerator Titanium, así que no tengo control sobre ella) y estoy bucleando algo para llamar a la función de prueba. Necesito romper el ciclo en la función onerror, pero me da un error que dice que el corte no está dentro de un bucle o declaración de cambio. ¿Cómo puedo reescribir esto?

+1

agradecimiento que responder único voto en el pasado, pero ahora sé para golpear la marca de verificación – eirikrl

Respuesta

11

Si el ejemplo de código Qué representa algún código real (es decir, todo el procesamiento se realiza en la misma garrapata bucle de eventos), puede hacer lo siguiente:

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

De lo contrario, si hay algo asíncrono hecho, usted tiene que llamar test secuencialmente, y no en paralelo. Por ejemplo,

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); 
0

No se puede interrumpir el bucle dentro de la función de prueba(). Creo que la mejor solución en este caso sería arrojar una excepción dentro de la función test(), luego atraparla en el ciclo y romperla.

2

No es posible. Un bucle for es un procedimiento síncrono mientras que una solicitud Ajax no lo es. Eso significa que cuando se produce la devolución de llamada onerror, el bucle for ya está ejecutando .

Como alternativa, puede introducir un cheque en su controlador onsuccess que confirma que aún no ha ocurrido ningún error.

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


}); 
} 
0

¿Quizás pueda hacer que la devolución de llamada 'onload' sea recursiva?

Lo que significa que simplemente llama al método de 'prueba' dentro del controlador 'onload', esto también significa que debe iniciar todas las solicitudes en orden en lugar de todas al mismo tiempo.

3

Bit hacky tal vez, pero se podría hacer algo como esto con una función de controlador.

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

¿No ha probado esto pero tal vez podría vincular la función al alcance en la llamada incluso?

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

Tomo la respuesta de penartur, pero modificado sin la "ruptura":

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); 
Cuestiones relacionadas