在 Node.js 中处理异步循环的最佳模式 [英] The best pattern for handling async looping in Node.js

查看:40
本文介绍了在 Node.js 中处理异步循环的最佳模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm new to Node and trying to ensure that I'm using sane designs for a JSON-driven web app.

我有一堆数据存储在 Redis 中,我正在通过 node 检索它,将结果从 Redis 中流出.这是我正在做的一个很好的例子:

I've got a bunch of data stored in Redis and am retrieving it through node, streaming out the results as they come from Redis. Here's a good example of what I'm doing:

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 的字符串已经在 J​​SON 中).现在这很好用,但我不禁想到 i == replies.length-1 有点不整洁?

Essentially I'm getting set of keys from Redis and then requesting each one, streaming out the result into semi-manually created JSON (the strings coming out of Redis are already in JSON). Now this works nicely, but I can't help thinking that the i == replies.length-1 is a little untidy?

我可以使用 Redis 中的 mget 完成所有这些,但这并不是我真正想要实现的重点;这是如何最好地使用 forEach 处理异步循环、流式传输输出并在循环完成后优雅地关闭与 res.end 的连接.

I could do all this with mget in Redis, but that isn't really the point I'm trying to get it; it's how best to handle async looping with forEach, streaming the output and gracefully closing off the connection with res.end with the looping is done.

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

Is this the best way, or is there a more elegant pattern I could follow?

推荐答案

上面的代码可能不符合您的预期.您按顺序启动每个 .get(),但它们可能不会按顺序回调 - 因此结果可以按任何顺序流出.如果要流式传输结果而不是将它们收集在内存中,则需要按顺序 .get().

The above code might not do what you expect. You're kicking off each .get() in sequence, but they might not call back in sequence — so the results could stream out in any order. If you want to stream the results instead of collecting them in memory, you need to .get() in sequence.

我认为 caolan 的异步库让这件事变得容易很多.这是您可以使用它按顺序获取每个项目的一种方法(警告,未经测试):

I think that caolan’s async library makes a lot of this easier. Here’s one way you could use it to get each item in sequence (warning, untested):

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() 代替.

If you don’t care about the order, just use async.forEach() instead.

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

If you wouldn’t mind collecting the results and want them to return in sequence, you could use async.map() like this (warning, also untested):

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(',') + ']');
            }
        });
    });
});

这篇关于在 Node.js 中处理异步循环的最佳模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆