简体   繁体   中英

How to convert a function to an async.each function

I've a small problem with a function in a class of my nodejs/express server.

I have the following function :

@resolveServers = (url, servers, resolved) ->
  result = []
  treatServer(url, server, (serverObject) ->
    result.push serverObject
    resolved result if result.length is servers.length
  ) for server in servers

And since the treat server function can take a wild, and as hinted on this question of mine, I was considering using async each for this.

So I'm here :

@resolveServers = (url, servers, resolved) ->
  result = []
  async.each(servers, treatServer(url, server, (serverObject) ->
    result.push serverObject
        resolved result if result.length is servers.length
  ), (err) ->
    if err 
      console.log next err
  )

And I currently get the following error :

ReferenceError: server is not defined

The treatServer function needs the url and a server for the servers array. But I don't know how to get this server instance for each one of them, and pass it to the treatServer function.

Any idea on what I'm doing wrong ?

Thanks already.

Update: I'm slightly disappointed as I have no gain at all using async. The function I used takes approximatively 6500ms and the async one is the same. I guess the each function from coffeescript does its job really well.

Update: After further tests, I'm finding out that the function is slower with async. Really wierd.

I think you want async.map instead: it gathers the results of all operations and passes them as an array to the final callback. It also maintains the order of the input array, which async.each doesn't (but that might not be an issue).

@resolveServers = (url, servers, resolved) ->
  async.map(servers, (server, callback) ->
    treatServer(url, server, (serverObject) ->
      callback null, serverObject
    )
  , (err, result) ->
    if err 
      console.log next err
    resolved err, result // see text
  )

Since my CF isn't that great, a JS version too:

function resolveServers(url, servers, resolved) {
  async.map(servers, function(server, callback) {
    treatServer(url, server, function(serverObject) {
      callback(null, serverObject);
    });
  }, function(err, result) {
    if (err)
      console.log(err);
    resolved(err, result);
  });
}

I would also suggest following the common Node idiom for asynchronous callbacks, where the first argument is an error object (or null is no errors occurred), and the second argument the result value. That way, you can propagate your errors all the way back the calling chain.

The iterator function of async.each takes two parameters like this:

async.each(openFiles, 
  function(file, callback) {
    // do something with file
    callback()
  }, function(err){
    // if any of the saves produced an error, err would equal that error
});

in your case you get a server and a callback, so I would rewrite to something like this:

@resolveServers = (url, servers, resolved) ->
  result = []
  async.each(servers, (server, callback) ->
    treatServer(url, server, (serverObject) ->
      result.push serverObject
      resolved result if result.length is servers.length
      callback()
    )  
  , (err) ->
    if err 
      console.log next err
  )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM