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希望停止“提前”的愿望,我怀疑他们想要连续做事。如果我发现我需要经常使用“减少”,我肯定会给自己一个帮手。 –