我是节点新手,无法理解节点的异步行为。我知道这是关于SO的一个经常被解决的问题,但我根本无法理解如何获得我在上下文中阅读的任何解决方案。
我正在编写这个模块,我想返回一个包含各种数据的对象。
var myModule = (function () {
var file,
fileArray,
items = [],
getBlock = function (fileArray) {
//get the data from the file that I want, return object
return block;
},
parseBlock = function (block) {
//[find various items in the block, put them into an "myItems" object, then
//take the items and do a look up against a web api as below]...
for (var i = 0, l = myItems.length; i < l; i ++) {
(function (i) {
needle.post(MY_URL, qstring, function(err, resp, body){
if (!err && resp.statusCode === 200){
myItems[i].info = body;
if (i === (myItems.length -1)) {
return myItems;
}
}
});
})(i);
}
},
getSomeOtherData = function (fileArray) {
//parse some other data from the file
}
return {
setFile: function (file) {
fileArray = fs.readFileSync(file).toString().split('\n');
},
render: function () {
var results = [];
results.someOtherData = getsomeOtherData();
var d = getBlock();
results.items = parseBlock(d);
return results;
}
}
})();
当我使用以下方式调用此模块时:
myModule.setFile('myFile.txt');
var res = myModule.render();
变量res
具有someOtherData
属性的值,但不具有items
属性的值。据我所知,我的长时间运行的http请求尚未完成,该节点只是放大并完成执行,但这不是我想要的。我查看了一堆SO问题,并查看了使用Q或queue-async,但没有成功。
在完成所有请求之前,如何让此模块不返回任何数据?或者在节点中甚至可能?有没有更好的方法来设计它来实现我的目标?
答案 0 :(得分:0)
您的示例中的问题是您调用getBlock()但您已将函数声明为getBlockData()。所以你不会得到结果。尝试将其更改为两者。
假设你有两个相同,你的下一个问题是你从一个文件处理数据,所以我假设你读取文件的内容然后解析它。
如果是这种情况,那么可以使用同步读取来强制同步,但我不建议这样做。
您真的想根据事件构建程序。你在'召唤函数,当它返回时继续'的范式中的思考。你需要更多地思考'调用一个进程并添加一个监听器,然后监听器进行回复处理'。
这对于通讯非常有效。您收到了请求。您需要根据文件内容进行回复。因此,您可以使用两种可能的结果开始读取过程。它调用已完成的函数或错误函数。然后两者都会调用reply函数来处理如何处理请求的回复。
重要的是不要阻止,因为你将阻止处理所有进程的线程。
希望有帮助,如果没有添加一些评论,我会尽力详细说明。
查看this answer to another question以查看使用标准侦听器处理文件的一个很好的示例。所有异步调用都有一个监听器概念,可以发生什么。您需要做的就是在调用时将函数名称(或者如果您愿意,或者是anon)传递给它们。
一个简单示例(基于node.js stream.Readable API:
fs.createReadStream(filename, {
'flags': 'r'
}).addListener( "data", function(chunk) {
// do your processing logic
}).addListener( "end", function(chunk) {
// do your end logic
response(...);
}).addListener( "error", function(chunk) {
// do your error logic
response(...);
}).addListener( "close",function() {
// do your close logic
});
function response(info) {
}