如何使用nodejs使用异步回调?

时间:2017-02-28 19:18:40

标签: javascript node.js asynchronous callback

我有搜索功能一旦我有来自clinet的搜索字符串我想循环浏览文件并匹配fs文件中的字符串,我在循环中遇到问题我希望得到所有匹配结果并将结果发送到客户端。下面试图实现,但得到一个错误粘贴有问题。异步库新手任何帮助将不胜感激。

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

var fs = require('fs');
var path = require('path');
var async = require('async');
var searchStr;
var result = [];


//Async Method
function readFile(str, logFiles, callback) {
    async.series([
        //Load user to get `userId` first
        function(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(result);
            }
        },
        //Load posts (won't be called before task 1's "task callback" has been called)
        function() {
            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;
                    }
                });
            }
        }
    ], function(err) { //This function gets called after the two tasks have called their "task callbacks"
        if (err) return err;
    });
};

错误

  if (fn === null) throw new Error("Callback was already called.");

2 个答案:

答案 0 :(得分:1)

您应该使用async.map而不是系列。你很想知道系列是什么,系列处理请求自上而下。您试图通过访问系列本身内的函数来打破此链。哪个是不,不。

例如:

async.series([
    function() {
        let i = 0;
        do {
            console.log("I'm first in the series: ", i);
            i++;
        } while (i < 3);
        callback(); // This tells us this function has finished.
    },
    function() {
        let i = 0;
        do {
            console.log("I'm next in the series: ", i);
            i++;
        } while (i < 3);
        callback(); // This tells us this function has finished.
    }
]);

这个的输出是:

I'm next in the series: 0

I'm next in the series: 1

I'm next in the series: 2

直到回调被触发,然后告诉异步移动到系列数组中的下一个函数。

然后输出为:

I'm last in the series: 0

I'm last in the series: 1

I'm last in the series: 2

在本系列中,您不应该在当前之后访问该系列中的函数。因此,您永远不应该尝试跨越访问权限。

使用async.map,您实际上可以对阵列中的每个实体执行操作,这基本上就是您要做的事情。

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

另外你应该使用util.inspect而不是console.log,它更干净,有更多的选择。

关于此的文档有点粗糙,但现在是。 https://caolan.github.io/async/docs.html#map希望这会有所帮助!

答案 1 :(得分:0)

您应该使用async.eachSeries method

function readFile(str, logFiles, callback) {
    async.eachSeries(array, function(item, cb){
       //Process item
       cb(error,item);
    }, function(err){
       if (err) {
           console.log("Some error in one of the items");
           callback(err);
       } else {
           console.log("All arrays items have been treated successfully");
           callback(null);
       }
    });
}

我建议在使用 async.eachSeries 功能之前加载用户帖子