2017-03-06 108 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 

     }); 
    } 

如何打破承諾的循環?如何在承諾中打破循環?

我使用節點明確,sequelize模塊

+1

試圖混合同步和異步代碼只會導致流淚。 – Adam

+0

你想結束循環嗎?或者因爲錯誤而結束整個腳本? –

+1

那麼,一般來說,除非鏈接它們,否則不會破壞異步操作循環。是的,您可以設置一個標誌,然後在每個步驟中對該標誌進行查詢 - 但該標誌只會在下一堆命令中進行檢查。 – raina77ow

回答

2

循環將在第一then觸發回調之前;這是承諾的保證之一(假設create操作返回一個合適的承諾,而不僅僅是一個可承諾的;或者至少它的返回值異步完成)。

您可以使用reduce技巧循環添加這些成分連續(一次一個);承諾拒絕沿途將跳過其餘成分:

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]',請點擊刷新。)* –

+0

+1,很好的答案。我不知道這是否是虛構的'Promise.raceTillReject()'方法的用例,當它的所有參數承諾都解決了,或者任何被拒絕時,這個方法就完成了。 – raina77ow

+1

@ raina77ow:這就是'Promise.all'所做的(https://jsfiddle.net/von1zduc/1/)。事情是,如果您事先調用'create'來構建參數promise,這些'create'調用已經並行進行。這通常是你想要的(見答案的結尾),但是從OP希望停止「提前」的願望,我懷疑他們想要連續做事。如果我發現我需要經常使用「減少」,我肯定會給自己一個幫手。 –