Node.js的&安培; Redis的;等待一个循环完成 [英] Node.js & Redis; Waiting for a loop to finish

查看:209
本文介绍了Node.js的&安培; Redis的;等待一个循环完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想问一下这个问题,因为我不知道如果我得到了Node.js的逻辑权

I would like to ask this question, because I'm not sure if I got the Node.js logic right

我有一组编号的,我需要使用Redis的get方法来查询的。和检查一定值后(比方说,即时通讯检查我给钥匙获得对象是否有一个空的名字),我将它们添加到列表中。这里是我的例子code;

I have a set of id's that I need to query using redis' get method. And after checking a certain value(let's say that im checking whether the object I get with given "key" has a null name), I add them to a list. Here is my example code;

var finalList = [];
var list = [];
redisClient.smembers("student_list", function(err,result){
            list = result; //id's of students
            console.log(result);

            var possibleStudents = [];


            for(var i = 0; i < list.length; i++){


                redisClient.get(list[i], function(err, result){
                    if(err)
                        console.log("Error: "+err);
                    else{
                        tempObject = JSON.parse(result);
                        if(tempObject.name != null){
                            finalList.push(tempObject);
                        }
                    }
                });     
            }

    });
   console.log("Goes here after checking every single object");

但由于节点的异步性预期,没有在列表检查每一个ID它执行在这儿... ...。我需要的是每个ID进行检查(在Redis的数据库映射和检查名称)后应用程序的其余部分。但我不知道该怎么做。也许我可以将回调至for循环,并保证在我的职务其余启动循环结束后,运行(我知道这是不可能的,但只给一个想法)?

But as expected due to the async nature of Node, without checking every single id in the list it executes the "Goes here...". My need is to apply the rest of procedures after every id is checked(mapping in redis db and checking the name). But I do not know how to do it. Maybe if I can attach callback to the for loop and assure the rest of my functions start to run after loop is finished(i know it's impossible but just to give an idea)?

推荐答案

我会去你在你的问题建议的路线,并附加一个自定义的回调到你的抓取功能:

I would go the route you suggest in your question and attach a custom callback to your fetching function:

function getStudentsData(callback) {
    var setList = [];
    var dataList = [];

    redisClient.smembers("student_setList", function(err,result) {
        setList = result; //id's of students

        for(var i = 0; i < setList.length; i++) {
            redisClient.get(setList[i], function(err, result) {
                if(err) {
                    console.log("Error: "+err);
                } else {
                    tempObject = JSON.parse(result);
                    if(tempObject.name != null) {
                        dataList.push(tempObject);
                    }
                }
            });     
        }

        if(dataList.length == setList.length) {
            if(typeof callback == "function") {
                callback(dataList);
            }
            console.log("getStudentsData: done");
        } else {
            console.log("getStudentsData: length mistmach");
        }

    });
}

getStudentsData(function(dataList) {
    console.log("Goes here after checking every single object");
    console.log(dataList.length);
    //More code here
});

这可能是最有效的方法;或者你可以依靠一个老同学的,而循环,直到数据准备好:

That's probably the most efficient method; alternatively you could rely on an old school while loop until the data is ready:

var finalList = [];
var list = [0];

redisClient.smembers("student_list", function(err,result) {
    list = result; //id's of students
    var possibleStudents = [];

    for(var i = 0; i < list.length; i++) {
        redisClient.get(list[i], function(err, result) {
            if(err) {
                console.log("Error: "+err);
            } else {
                tempObject = JSON.parse(result);
                if(tempObject.name != null) {
                    finalList.push(tempObject);
                }
            }
        });     
    }
});


process.nextTick(function() {
    if(finalList.length == list.length) {
        //Done
        console.log("Goes here after checking every single object");
        console.log(dataList.length);
        //More code here
    } else {
        //Not done, keep looping
        process.nextTick(arguments.callee);
    }
});

我们使用 process.nextTick ,而不是实际的,而,以确保其他请求不会被阻止在此期间;是因为JavaScript的单线程性质,这是preferred方式。我在此扔为了完整起见,但前一种方法更高效,更适合用Node.js的好,所以除非有重大改写参与去了。

We use process.nextTick instead of an actual while to make sure other requests are not blocked in the meantime; due to the single threaded nature of Javascript this is the preferred way. I'm throwing this in for the sake of completeness, but the former method is more efficient and fits better with node.js, so go for it unless a major rewrite is involved.

这是值得什么,这两种情况下依靠异步回调,这意味着任何code外面别人完成之前仍然可以潜在地运行。例如,使用我们的第一个片段:

It's worth nothing that both cases rely on async callbacks, which means any code outside it can still potentially run before others are done. E.g., using our first snippet:

function getStudentsData(callback) {
    //[...]
}

getStudentsData(function(dataList) {
    //[...]
});

console.log("hello world");

这最后的console.log几乎可以保证我们的回调传递给getStudentsData被炒鱿鱼之前运行。解决方法?设计它,这是多么的node.js的作品。在我们的例子上面很容易,我们只是会叫的console.log的只有的在回调传递给getStudentsData,而不是外面。其他方案需要离开多一点从传统的程序编码解决方案,但一旦你得到你的头周围,你会发现是事件驱动和无阻塞实际上是pretty强大的功能。

That last console.log is almost guaranteed to run before our callback passed to getStudentsData gets fired. Workaround? Design for it, it's just how node.js works. In our case above it's easy, we just would call console.log only in our callback passed to getStudentsData and not outside it. Other scenarios require solutions that depart a bit more from traditional procedural coding, but once you get your head around it you'll find being event-driven and non-blocking is actually a pretty powerful feature.

这篇关于Node.js的&安培; Redis的;等待一个循环完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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