【问题标题】:Callback is already called using async?已经使用异步调用了回调?
【发布时间】:2017-03-02 01:41:46
【问题描述】:

一旦fs.readFile 循环遍历所有文件并获取匹配数据并将其推送到结果中,我想调用callback(results) 以便向客户端发送响应。我收到以下代码Error: Callback is already called 的错误我如何使用async 方法解决此问题。

app.js

searchFileService.readFile(searchTxt, logFiles, function(lines, err) {
    console.log('Logs', lines);
    if (err)
        return res.send();
    res.json(lines);
})

readFile.js

var searchStr;
var results = [];

function readFile(str,logFiles,callback){
   searchStr = str;
    async.map(logFiles, function(logfile, callback) {
           fs.readFile('logs/dit/' + logfile.filename, 'utf8', function(err, data) {
               if (err) {
                   callback(null,err);
               }
               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
                       results.push(line);
                       callback(results,null);
                   }
               });
            });
    }), function(error, result) {
         results.map(result,function (result){
             console.log(result);
         });
    };
}

【问题讨论】:

  • 尝试反转参数:callback(results, null);结果正常
  • 在 app.js 中我尝试传递第一个错误,例如 function(err,lines)
  • 是的,但是当一切正常时,参数被反转

标签: javascript node.js async.js


【解决方案1】:

注意:此答案是trincot's answer 的扩展。因此,如果这回答了您的问题,请将其标记为答案!

您说:一旦 fs.readFile 循环遍历所有文件并获取匹配的数据并将其推送到结果中,老实说,我认为 .map 不适合此功能.这是为了将数组中的每个元素转换为另一个不是你正在做的事情。

更好的方法是.eachSeries 一次读取一个文件。

最好将您的第二个 callback 重命名为其他名称,例如done 不要让自己(和其他人)感到困惑。调用done() 是为了告诉我们对文件的操作已经完成,就像我们“完成”读取文件一样。

最后,请注意您的拼写错误。第一个可能会阻止您进入最后一部分。

var results = [];
var searchStr;

function readFile(str, logFiles, callback) {
    searchStr = str;
    // loop through each file
    async.eachSeries(logFiles, function (logfile, done) {
        // read file
        fs.readFile('logs/dit/' + logfile.filename, 'utf8', function (err, data) {
            if (err) {
                return done(err);
            }
            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
                    results.push(line);  
                }
            });
            // when you are done reading the file
            done();
        });

    // wrong: }), function (err) {
    }, function (err) {
        if (err) {
            console.log('error', err);
        }
        console.log('all done: ', results);

        // wrong: results.map(result, function (result){
        results.map(function (result){
            console.log(result);
        });

        // send back results
        callback(results);
    });
}

【讨论】:

  • 用你的方法我得到了results到客户端,有问题假设如果用户serachid0536如果任何行包含这个id,它将第一次呈现结果,两个问题# 1 如果我搜索相同的字符串两次,它会推送相同的数组并作为两行发送 #2 如果我使用不同的字符串值进行搜索,它会发送第一次搜索的结果。
  • @Mikey,很明显,双 callback 变量在我的回答中让我感到困惑,我将删除 (+1)。
  • @hussain,由于您的问题已明确得到解答,请作为新问题提出任何后续问题。
猜你喜欢
  • 2017-08-04
  • 2014-08-19
  • 1970-01-01
  • 2017-09-15
  • 1970-01-01
  • 2015-02-15
  • 2017-03-02
  • 2018-11-06
  • 2021-11-23
相关资源
最近更新 更多