简体   繁体   中英

Callback was already called in async module

I have the following array:

var files = [
 {
  name: 'myfile.txt'
 },
 {
  name: 'myfile2.txt'
 }
];

I'm using async for access this objects and send them to extraction, like this:

extraction function:

var extraction = function(file, callback) {
  // extract

  // return text
  callback(text);
};

Using async

var fn = function(files, callback) {
  Async.mapLimit(files, 3000, function(file, done) {
   extraction(file, function(texts) {
     done(texts);
   });
  }
}, function(texts) {
  callback(texts);
}

How i need call:

fn(files, function(texts) {
 console.log(texts); // new objects, now with text's
});

Like this, i'm receiving the following error:

Done was already called.

This happens because i can't call the done inside the async two ways, and i'm doing that.

To around this problem, i'm doing this inside the Async:

if (files.length === texts.length) {
  done(texts);
}

So will compare. Files size is the same as texts size? Yes? So you can call the done.

This will work perfectly. The problem with this is that i can't pass a error argument inside a else statement, like this:

if (files.length === texts.length) {
  done(null, texts);
} else {
  done('ERROR'!);
}

First because would be call in every loop, so will cause the same error:

Done was already called.

And even if i could, would break the loop because will be called in the first looping.

How can i fix this? I need a light here :/

This code is not braced correctly and the callback arguments were not in the proper position in a couple of places:

var fn = function(files, callback) {
  Async.mapLimit(files, 3000, function(file, done) {
   extraction(file, function(texts) {
     done(texts);
   });
  }
}, function(texts) {
  callback(texts);
}

It should be:

var fn = function (files, callback) {
    Async.mapLimit(files, 3000, function (file, done) {
        extraction(file, function (texts) {
            done(null, texts);
        });
    }, function (err, texts) {
        callback(texts);
    });
}

Async.mapLimit() takes four arguments. You were not passing the fourth argument correctly. In fact, if you paste your code into http://jshint.com/ , it will show you where the errors are (frankly I'm surprised that the code even ran).

Here's an article that shows you some Async.mapLimit() coding examples that work just like you are trying to do: Concurrency level (async.mapLimit)

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