节点模块:在所有异步请求完成之前不要返回

时间:2013-12-20 00:22:57

标签: javascript node.js asynchronous

我是节点新手,无法理解节点的异步行为。我知道这是关于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问题,并查看了使用Qqueue-async,但没有成功。

在完成所有请求之前,如何让此模块不返回任何数据?或者在节点中甚至可能?有没有更好的方法来设计它来实现我的目标?

1 个答案:

答案 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) {
}