2012-08-07 16 views
9

内側のforループを壊す:Javascriptが、私は次のようなコードを持って、コールバック関数

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


    }); 
} 

要旨はテスト()関数では、XHRリクエストを作成する機能です(実際のAPIでありますAppcelerator Titaniumプラットフォームなので、私はそれを制御できません)、私はテスト関数を呼び出すために何かをループしています。私はonerror関数でループを解除する必要がありますが、breakがループまたはswitchステートメントの内部にないというエラーが表示されます。これをどのように書き換えることができますか?

+1

おかげで私は過去にアップ答える投票今私は、チェックマークを打つために知っています – eirikrl

答えて

11

あなたのコードサンプルは(つまり、すべての処理が同じイベントループティックで行われている)、いくつかの実際のコードを表していた場合は、次の操作を行うことがあります。

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

test()関数内でループを解除することはできません。この場合、最良の解決策はtest()関数内に例外をスローし、それをループ内で捕捉して中断することだと思います。

2

できません。 forループは、同期プロシージャですが、Ajaxリクエストは処理されません。つまり、エラー・コールバックが発生したとき、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; 
    } 


}); 
} 
0

「onload」コールバックを再帰的に行うことはできますか?

つまり、 'onload'ハンドラの中で 'test'メソッドを呼び出すだけであれば、同時にすべてのリクエストをすべてではなく順番に起動することになります。

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; 
    } 
}); 
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); 
関連する問題