Ramanathan Iyer
Ramanathan Iyer

Reputation: 11

Sending response after fs.readFile has finished executing iteratively

I have the following code

var express = require('express');
var Promise = require('bluebird');
var fs = Promise.promisifyAll(require('fs'));
var path = require("path");
var langs = fs.readdirSync({directory having multiple directories});
var arr = [];
for(var v in langs){
    var filename = config.path.storage + "/" + langs[v] +"/assets/_assets.json";
        fs.readFile(filename, "utf8", function(err, data) {
        if (err) throw err;
        res.write(data);
        //res.end();
    });
}
res.end();

What I want to do is, once all the files in the directories (lang in this case - langs contains: [ 'ar-dz', 'en-gb', 'en-us' ]) are read, I want to do a res.send() to the client.

I tried to promisify the 'fs' module via 'bluebird' module. I assume the callback in fs.readFileAsync() is causing the problem, is there a way around it?

Upvotes: 0

Views: 1369

Answers (1)

jfriend00
jfriend00

Reputation: 707476

Can't set headers after they are sent. is occurring because you are calling res.write() after you've called res.end(). This happens because the async response to fs.readFile() comes later after your for loop is done. Instead, you need to use your promises to coordinate the result of your async operations and when they are all done, you can then send your response with all the data.

You can use your Bluebird promise library to do that like this:

fs.readdirAsync(...).map(function(file) {
    return fs.readFileAsync(file, 'utf8');
}).then(function(arrayOfData) {
    res.send(arrayOfData.join(""));
}).catch(function(err) {
    // send some error response here
});

Upvotes: 1

Related Questions