1

Once I have parameters from the client, I want to match that string from the file system and send matching data back to client. I am trying to get familiar with callbacks, so in the code below, when I call the callback it sends me the response with correct data but its throwing an error - see below, after the pasted code.

app.js:

        app.get('/serverSearch', function (req, res) {
            var searchTxt = req.query.searchTxt;
            dirDirectory.readDirectory(function(logFiles){
                // res.json(logFiles);
                if(logFiles){
                    searchFileService.readFile(searchTxt,logFiles,function(lines,err){
                                console.log('Logs',lines);
                                  if (err)
                                   return res.send();
                                   res.json(lines);
                            })
                }
            });
            console.log('Search text', searchTxt);
        });

service.js:

function readFile(str,logFiles,callback){
    searchStr = str;
    for(var i=0; i<logFiles.length; i++){
        if(logFiles[i].filename !== '.gitignore'){
            fs.readFile('logs/dit/' + logFiles[i].filename, 'utf8', function (err,data) {
              if (err) {
                return console.log(err);
              }
              inspectFile(data,callback);
              callback(result);
              result = [];
            });
        }
    }

}

function inspectFile(data,callback) {
    var lines = data.split('\n');              // get the lines
    lines.forEach(function(line) {             // for each line in lines
        if(line.indexOf(searchStr) != -1) {    // if the line contain the searchSt
            result.push(line);
            // then log it
            return line;
        }
    });
    cb(callback);
}

function cb (callback) {
    callback(result);
}

Error:

_http_outgoing.js:344

throw new Error('Can\'t set headers after they are sent.');

^

Error: Can't set headers after they are sent.

kun zhang
  • 31
  • 2
  • 1
    "its throwing error" — **What error?!** – Quentin Feb 28 '17 at 16:06
  • Possible duplicate of [How do I return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Jared Smith Feb 28 '17 at 16:09
  • it throws this error: _http_outgoing.js:344 throw new Error('Can\'t set headers after they are sent.'); ^ Error: Can't set headers after they are sent. – kun zhang Feb 28 '17 at 16:10
  • @JaredSmith — Not a duplicate of that. Possibly a duplicate of http://stackoverflow.com/questions/18983138/callback-after-all-asynchronous-foreach-callbacks-are-completed – Quentin Feb 28 '17 at 16:20
  • @Quentin you are more correct than I. Same answer to both though. – Jared Smith Feb 28 '17 at 16:36

1 Answers1

0

Your callback function gets called multiple times, because it is inside a for loop.

The first time it runs, it will send a response.

The second time it runs, it will throw the error (because the response has been sent)

You need to refactor your code to only send a response after all instances of fs.readFile have been resolved.

General solutions to that problem are presented in the question: Callback after all asynchronous forEach callbacks are completed

Community
  • 1
  • 1
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335