Conditionally executing a callback within an asynchronous function call in a for loop
I'm working on a function that iterates through a list of ports and calls its callback once one of the ports is available. Instead of waiting for each port response, I'd like to call a checkPortStatus function on all the ports and return when the first port returns as available.
Here's sample code runnable in node.js:
// Check if a port is open (in use) or closed (available)
function check开发者_Go百科PortStatus(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)
Results of running the code:
AVAILABLE PORT: 3005
AVAILABLE PORT: 3007
AVAILABLE PORT: 3006
Two questions:
- How do I call the callback only once? I want only the first port that matches to return.
- How do I check if all function callbacks returned? In this example, I need to return when all checkPortStatus return ports as unavailable.
initializing a few variables outside of the function should do the trick:
// 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)
}
}
精彩评论