如何使用 nodejs 将异步用于回调?
Posted
技术标签:
【中文标题】如何使用 nodejs 将异步用于回调?【英文标题】:How to use async for callbacks using 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.");
【问题讨论】:
【参考方案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 函数之前加载 user 和 posts。
【讨论】:
您的代码正在运行,它打印所有已成功处理的数组,但未将结果发送到客户端 @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.
与我的代码相同的错误以上是关于如何使用 nodejs 将异步用于回调?的主要内容,如果未能解决你的问题,请参考以下文章