在Node.js中处理异步循环的最佳模式

发布于 2021-02-01 12:16:17

我是Node的新手,并试图确保我对JSON驱动的Web应用程序使用了合理的设计。

我已经在Redis中存储了一堆数据,并且正在通过node检索它们,并将结果从Redis中流出来。这是我正在做的一个很好的例子:

app.get("/facility", function(req, res) {
    rc.keys("FACILITY*", function(err, replies) {
        res.write("[");
        replies.forEach(function (reply, i) {
            rc.get(reply, function(err, reply) {
                res.write(reply);
                if (i == replies.length-1) {
                    res.write("]");
                    res.end();
                }
                else
                    res.write(",");
            });
        });
    });
});

本质上,我是从Redis获取一组密钥,然后请求每个密钥,然后将结果流式传输到半手动创建的JSON(来自Redis的字符串已经在JSON中)。现在,这很好用,但是我不禁会以为i
== replies.length-1有点不整洁?

我可以在Redis中使用mget来完成所有这一切,但这并不是我想要得到的重点。这是处理forEach异步循环,流式传输输出并优雅地用res.end关闭连接的最佳方法。

这是最好的方法,还是我可以遵循的更优雅的模式?

关注者
0
被浏览
164
1 个回答
  • 面试哥
    面试哥 2021-02-01
    为面试而生,有面试问题,就找面试哥。

    上面的代码可能无法满足您的期望。您将按.get()顺序开始每一个,但它们可能不会按顺序回叫-
    因此结果可以按任何顺序输出。如果要流式传输结果而不是将其收集到内存中,则需要.get()按顺序进行。

    我认为caolan的异步库使此操作变得更加容易。您可以使用以下一种方法来按顺序获取每个项目(警告,未经测试):

    app.get("/facility", function(req, res) {
        rc.keys("FACILITY*", function(err, replies) {
            var i = 0;
            res.write("[");
            async.forEachSeries(replies, function(reply, callback){
                rc.get(reply, function(err, reply) {
                    if (err){
                        callback(err);
                        return;
                    }
                    res.write(reply);
                    if (i < replies.length) {
                        res.write(",");
                    }
                    i++;
                    callback();
                });
            }, function(err){
                if (err) {
                    // Handle an error
                } else {
                    res.end(']');
                }
            });
        });
    });
    

    如果您不关心订单,请async.forEach()改用。

    如果您不介意收集结果并希望它们按顺序返回,则可以这样使用async.map()(警告,也未经测试):

    app.get("/facility", function(req, res) {
        rc.keys("FACILITY*", function(err, replies) {
            async.map(replies, rc.get.bind(rc), function(err, replies){
                if (err) {
                    // Handle an error
                } else {
                    res.end('[' + replies.join(',') + ']');
                }
            });
        });
    });
    


推荐阅读
知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看