2017-03-06 5 views
1
var ing_data = savedata.ingredients.split(',');  
for(var i =0; i<ing_data.length; i++){ 

     var d = { 
      content_name: ing_data[i], 
      dogFoodId: dogId 
     } 
     db.dog_ingredients.create(d).then(function(data){ 

     }, function(e){ 
      console.log(e); 

      res.status(403).send('Error'); 
      //break for loop this point 

     }); 
    } 

約束どおりループを破る方法は?約束どおりループを壊す方法は?

Iが最初thenコールバックがトリガされる前に、ループが上になり、ノードエクスプレス、sequelizeモジュール

+1

同期コードと非同期コードを混ぜようとすると、涙が出るだけです。 – Adam

+0

ループを終了するだけですか?またはエラーのためにスクリプト全体を終了しますか? –

+1

一般的に、非同期操作ループは、連鎖しない限り中断しません。はい、フラグを設定してから各ステップでこのフラグを照会できますが、フラグは次のコマンドスタックでのみチェックされます。 – raina77ow

答えて

2

を使用しています。これは約束の保証の1つです(createオペレーションは、単に返すことができない、または返されるthenableが非同期に完了することを前提としています)。

reduceトリックを使用して、これらの成分をループさせることができます。(1度に1つ);途中で約束を拒否すると、残りの成分は飛び越されます:

savedata.ingredients.split(',').reduce(function(p, ing) { 
    // Chain this ingredient on the end of the promise, return 
    // the new promise `then` returns, which gets passed to the 
    // next iteration 
    return p.then(function() { 
     var d = { 
      content_name: ing, 
      dogFoodId: dogId 
     }; 
     // Return the promise from `create` 
     return db.dog_ingredients.create(d); 
    }); 
}, Promise.resolve()/* Seeds the loop above */) 
.catch(function(e) { 
    // We got a rejection, which bypasses any pending resolution 
    // handlers we set up above; process the rejection. 
    console.log(e); 
    res.status(403).send('Error'); 
    return Promise.reject(e); // Only need to propgate the rejection like this 
           // this if something will use the return value of 
           // this overall structure 
}); 

これは大部分ですが、それは主にコメントとオブジェクト初期化子です。我々はまた、(私たちが拒否伝播する必要はありませんでしたと仮定して)このようにそれを書くことができます:

savedata.ingredients.split(',').reduce(function(p, ing) { 
    return p.then(function() { 
     return db.dog_ingredients.create({ content_name: ing, dogFoodId: dogId }); 
    }); 
}, Promise.resolve()) 
.catch(function(e) { 
    res.status(403).send('Error'); 
}); 

を(またはあなたがさらに小さく得ることができますが、私はデバッグのためminifierに  —休暇により縮小を受けます。)


私は、あなたが「最初」のエラーで停止したい示さましたので、並列に成分を追加しないと仮定します。しかし、あなたがした場合、コードは単純に次のようになります。

Promise.all(savedata.ingredients.split(',').map(function(ing) { 
    return db.dog_ingredients.create({ content_name: ing, dogFoodId: dogId }); 
}).catch(function(e) { 
    res.status(403).send('Error'); 
    return Promise.reject(e); 
}); 

(。我々は拒絶反応を伝播する必要はありませんと仮定し)

再び、しかし、それはパラレルです。

+0

*(Doh!上記の 'ing_data [i]'が表示された場合は、refreshを押してください。)* –

+0

+1、素晴らしい答え。すべてのparam promiseが解決されたとき、またはanyが拒否されたときに完了する架空の 'Promise.raceTillReject()'メソッドのユースケースではないのだろうか。 – raina77ow

+1

@ raina77ow:それは 'Promise.all'がすることです(https://jsfiddle.net/von1zduc/1/)。つまり、事前に 'create'を呼び出してparam約束を構築すると、それらの' create'呼び出しはすでに並行して実行されています。あなたがしばしば望むもの(答えの終わりを見てください)ですが、「早期に」止めるというOPの希望から、私は彼らが連続してやりたいと思っていました。私が「reduce」を頻繁に行う必要があることが判明した場合、私は間違いなく自分自身に助力を与えるでしょう。 –

関連する問題