【问题标题】:How to use async for callbacks using nodejs?如何使用 nodejs 将异步用于回调?
【发布时间】:2017-07-19 21:54:57
【问题描述】:

一旦我从 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.");

【问题讨论】:

    标签: javascript node.js asynchronous callback


    【解决方案1】:

    你应该使用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 函数之前加载 userposts

    【讨论】:

    • 您的代码正在运行,它打印所有已成功处理的数组,但未将结果发送到客户端
    • @hussain 现在呢?我已经更新了答案。我不知道您还需要解决对客户端的回调。
    【解决方案2】:

    您应该使用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

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

    然后输出将是:

    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希望对您有所帮助!

    【讨论】:

    • 我正在尝试解决您的代码中的一些语法问题
    • 是的,对不起,我混合了 ES6 和 ES5,但它应该接近你需要的。希望对您有所帮助!
    • @hussain 是的,这就是告诉地图继续前进的原因。
    • 得到了你,nodejs 的新手,我试图修复它令人困惑的语法错误,但如果你能帮助修复它,我会很感激它
    • 语法问题解决后出现此错误if (fn === null) throw new Error("Callback was already called."); ^ Error: Callback was already called. 与我的代码相同的错误
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-15
    • 2018-06-14
    • 1970-01-01
    • 1970-01-01
    • 2017-12-08
    • 1970-01-01
    相关资源
    最近更新 更多