【问题标题】:Break out of a "for" loop within a callback function, in Node.js在 Node.js 中的回调函数中打破“for”循环
【发布时间】:2016-04-28 18:11:15
【问题描述】:

关于下面的代码,我的目标是跳出 FOR LOOP B 并继续 FOR LOOP A,但在回调函数中。

for(var a of arrA) {
    // ...
    // ...

    for(var b of arrB) {
        // ...
        // ...

        PartService.getPart(a.id, function(err, returnObj) {
            break;
        });
    }
}

这会给我想要的结果吗?如果没有,我该如何实现?


编辑 4/28/16 3:28 MST

  • 回调函数确实是异步的

基于其中一个答案和下面的所有 cmets,在不改变问题范围的情况下,也许此时最好的问题是“如何在 Node.js 中实现同步回调函数?”。我正在考虑重构我的代码以删除 for 循环,但我仍然很好奇我是否仍然可以使用同步回调函数朝这个方向发展。我知道Underscore.js使用了同步回调函数,但是不知道怎么实现。

【问题讨论】:

  • “这会给我想要的结果吗?” ——你试过了吗?
  • 为什么PartService.getPart首先要回调?是异步的吗?
  • break 只能在循环内。回调引入了一个新边界,因此在 for 循环内不考虑它。此外,在执行回调之前,两个循环都将运行完成(假设它是异步的)。循环是同步的,因此它们不能很好地播放异步代码(在它们的主体中)。首先阅读有关 JavaScript 中的异步代码流的更多信息可能对您很有用。
  • 感谢 Felix Kling,是的,它是异步的。我从未听说过同步回调函数。我实际上是在尝试将 PHP 代码转换为 JavaScript,看来我需要多花点心思。
  • 这个break应该给你一个运行时错误,或者只是被忽略,因为它不在循环中。

标签: javascript node.js return break asynccallback


【解决方案1】:

你可以尝试这样的事情,但是只有当回调被同步触发时它才会起作用。

for(var a of arrA) {
  let shouldBreak = false;
  for(var b of arrB) {
    if (shouldBreak)
      break;
   // rest of code
     PartService.getPart(a.id, function(err, returnObj) { // when the callback is called immediately it will work, if it's called later, it's unlikely to work
       shouldBreak = true;
    });

【讨论】:

  • 为什么函数需要回调,如果它不异步?
  • @Alexander: .sort, .map, .forEach, .filter 都接受“回调”但不是异步的。但是,是的,这个函数的命名/结构似乎表明它是异步的。
  • @FelixKling 是的,你说得对,我的问题表述不太正确。
  • @AlexanderMac,正如 Felix 指出的那样,函数不必是异步的,但在 NodeJS 的世界中,大多数回调代表异步的东西。但是我只发布了这个想法,并标记了它只有在同步的情况下才有可能。
  • 如果我想坚持循环,我将如何使回调同步?这似乎是最好的问题,而不是原始问题的范围。
【解决方案2】:

这可能不会给你预期的结果。您可以使用事件EventEmitterasync 模块。

【讨论】:

    【解决方案3】:

    您也可以尝试让它在没有for 循环的情况下自行循环。使其异步。

    for (var a of arrA) {
        var _loop = function(i) {
    
            // Make modifications to arrB
            
            PartService.getPart(id, function(err, retObj) {
                if (err) {
                    throw err;
                }
    
                if (retObj.success) {
                    // If successful, call function again
                    _loop(i + 1);
                } else {
                    // We've broken out of the loop
                }
            });
        };
        // Instantiate loop
        _loop(0);
    }
    

    【讨论】:

      猜你喜欢
      • 2018-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-25
      • 1970-01-01
      相关资源
      最近更新 更多