在 for 循环中的异步函数调用中有条件地执行回调

Posted

技术标签:

【中文标题】在 for 循环中的异步函数调用中有条件地执行回调【英文标题】:Conditionally executing a callback within an asynchronous function call in a for loop 【发布时间】:2011-10-24 14:58:20 【问题描述】:

我正在开发一个函数,它遍历端口列表并在其中一个端口可用时调用其回调。我不想等待每个端口响应,而是想在所有端口上调用 checkPortStatus 函数,并在第一个端口返回可用时返回。

这是可在 node.js 中运行的示例代码:

    // Check if a port is open (in use) or closed (available)
    function checkPortStatus(port, callback) 
      // Simulates real world checking of response from port by returning
      // after a random time.
      setTimeout(function() 
        // Simulates a few closed ports
        if (port === 3005 || port === 3006 || port === 3007) 
          callback('closed')
        
        // Simulates a few open ports
        else 
          callback('open')
        
      , Math.floor(Math.random() * 200))
    

    // Calls callback once any available port is found
    function findAnAvailablePort(startPort, endPort, callback) 
      var check = function(port) 
        checkPortStatus(port, function(status) 
          // If a port is 'closed', it's considered available
          if (status === 'closed') 
            callback(port)
          
        )
      
      for (var port = startPort; port <= endPort; port++) 
        check(port)
      
    

    findAnAvailablePort(3000, 3010, function(port) 
      console.log('AVAILABLE PORT: ' + port)
    );

    // Don't exit Node, wait for a response
    setTimeout(function()  console.log('FIN') , 5000)

代码运行结果:

AVAILABLE PORT: 3005
AVAILABLE PORT: 3007
AVAILABLE PORT: 3006

两个问题:

    如何只调用一次回调?我只想返回匹配的第一个端口。 如何检查所有函数回调是否返回?在这个例子中,当所有 checkPortStatus 都返回端口不可用时,我需要返回。

【问题讨论】:

【参考方案1】:

在函数之外初始化一些变量应该可以解决问题:

// Calls callback once any available port is found
var hasFoundPort = false;
var checkedPorts = 0;
function findAnAvailablePort(startPort, endPort, callback) 
  var check = function(port) 
    checkPortStatus(port, function(status) 
      checkedPorts++;
      // If a port is 'closed', it's considered available
      if (status === 'closed' && !hasFoundPort)  // only execute callback once
        callback(port)
        hasFoundPort = true;
      
      if(checkedPorts == endPort - startPort + 1) // checked all ports
          console.log('finished checking');
    )
  
  for (var port = startPort; port <= endPort; port++) 
    check(port)
  

【讨论】:

当一个端口已经找到时,你也应该关闭其他端口。 谢谢大卫,我想太多了。你的解决方案奏效了。代码可以在这里找到:github.com/baalexander/node-portscanner

以上是关于在 for 循环中的异步函数调用中有条件地执行回调的主要内容,如果未能解决你的问题,请参考以下文章

回调不是使用节点 js 的异步模块的 mongodb 查询中的函数

js执行顺序+同步异步

立即从同步代码执行异步回调

js的for循环中出现异步函数,回调引用的循环值总是最后一步的值?

理解闭包同步异步的最好例子

进阶学习5:JavaScript异步编程——同步模式异步模式调用栈工作线程消息队列事件循环回调函数