I have the following piece of code, but due to it's async behavior (I suppose), the callback is called twice. I'm using node-unzip
to unzip a file I download from the internet.
function DownloadAndExtract(file, callback) {
log.debug("Starting download of "+file);
fse.ensureDirSync(tempPath);
var extractor = unzip.Extract({path: tempPath});
extractor.on("close", function() {
log.debug("Done downloading "+file);
return callback(null, file);
});
extractor.on("error", function (err) {
log.error("Extracting download "+file+": "+JSON.stringify(err, null, "\t"));
return callback(err, null); // THIS IS LINE 274
});
var url = "";
if(file == "WONEN") {
url = "https://example.com/file1.zip";
}else if(file == "BOG") {
url = "https://example.com/file2.zip";
}
if(url != "") {
request
.get(url)
.on("error", function (err) {
return callback(err, null);
})
.pipe(extractor);
}else{
return callback(new Error("Invalid file indicator: '"+file+"'"), null);
}
}
I expected return to actually quit all running async functions but that is obviously nonsense. Now, the error I keep getting is the following:
/home/nodeusr/huizenier.nl/node_modules/async/lib/async.js:30
if (called) throw new Error("Callback was already called.");
^
Error: Callback was already called.
at /home/nodeusr/huizenier.nl/node_modules/async/lib/async.js:30:31
at /home/nodeusr/huizenier.nl/node_modules/async/lib/async.js:251:21
at /home/nodeusr/huizenier.nl/node_modules/async/lib/async.js:575:34
at Extract.<anonymous> (/home/nodeusr/huizenier.nl/realworks.js:274:10)
at Extract.emit (events.js:129:20)
at Parse.<anonymous> (/home/nodeusr/huizenier.nl/node_modules/unzip/lib/extract.js:24:10)
at Parse.emit (events.js:107:17)
at /home/nodeusr/huizenier.nl/node_modules/unzip/lib/parse.js:60:12
at processImmediate [as _immediateCallback] (timers.js:358:17)
The output of the log.error()
call is the following:
21-02-2015 03:00:05 - [ERROR] Extracting download WONEN: {}
so I'm quite confused. There isn't really an error, then why is the event emitted?
How would I prevent the callback from being called twice here? Contacting the creator of the package or create a work around?
Code calling DownloadAndExtract
async.parallel([
function (callback) {
DownloadAndExtract("WONEN", callback);
},
function (callback) {
DownloadAndExtract("BOG", callback);
}
],
function (err, done) {
if(err) return log.error("Update entries: "+JSON.stringify(err, null, "\t"));
// Do different logic if no error
});
Edit
One of my attempts is declaring a var callbackAlreadyCalled = false
within the function, and at any given point where I call the callback, I do
if(!callbackAlreadyCalled) {
callbackAlreadyCalled = true;
return callback(callback params);
}
Is this a good approach or could I handle it in a better way?
Edit 2
Already found out that the empty error is caused by errors not working properly when using JSON.stringify()
, however, problem doesn't change.