当前位置: 首页 > 面试题库 >

Node.js和Redis; 等待循环结束

彭海阳
2023-03-14
问题内容

我想问这个问题,因为我不确定我是否正确使用了Node.js逻辑

我有一组ID,需要使用redis的get方法进行查询。在检查了某个值之后(假设我正在检查通过给定的“键”获取的对象是否具有空名称),然后将它们添加到列表中。这是我的示例代码;

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");

但是由于Node的异步特性,正如预期的那样,如果不检查列表中的每个id,它将执行“ Goes here
…”。我的需要是在检查每个id之后应用其余过程(在redis
db中进行映射并检查名称)。但是我不知道该怎么做。也许我可以将回调附加到for循环并确保其余功能在循环结束后开始运行(我知道这是不可能的,但只是给出一个想法)?


问题答案:

我会按照您在问题中建议的路线进行操作,并将自定义回调附加到您的提取函数中:

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
});

那可能是最有效的方法。或者,您可以依靠旧的while循环,直到数据准备就绪:

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而不是实际的方法while来确保在此期间其他请求不会被阻止;由于Javascript具有单线程特性,因此这是首选方式。为了完整起见,我将其放入其中,但是前一种方法效率更高,并且更适合与node.js配合,因此,除非涉及重大重写,否则请继续进行下去。

两种情况都依赖异步回调是毫无价值的,这意味着它之外的任何代码仍然可以在其他代码完成之前运行。例如,使用我们的第一个片段:

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

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

console.log("hello world");

几乎可以保证最后一个console.log在触发传递给getStudentsData的回调之前可以运行。解决方法?为此进行设计,这就是node.js的工作方式。在上面的例子中,这很容易,我们
在传递给getStudentsData的回调中调用console.log
,而不在其外部调用。其他场景要求的解决方案与传统的过程编码有更多的区别,但是一旦掌握了这一点,您就会发现事件驱动和非阻塞实际上是一个非常强大的功能。



 类似资料:
  • 问题内容: 我正在使用bluebird,方法 getAll 和 update return promises。我如何说“等到两个承诺返回,然后更新currentProduct值”?我对JS很陌生… 问题答案: 如果可以使用/,这将很简单。 或者,如果您只能使用简单的承诺,则可以遍历所有产品,并将每个承诺置于最后一个循环中。这样,仅当前一个问题解决时,它才会前进到下一个问题(即使它将首先迭代整个循环

  • 本文向大家介绍JavaScript 异步等待循环,包括了JavaScript 异步等待循环的使用技巧和注意事项,需要的朋友参考一下 示例 在循环中使用异步等待时,您可能会遇到其中一些问题。 如果您只是尝试在内部使用await forEach,则会抛出Unexpected token错误。 这是因为您错误地将箭头功能视为一个块。该await会在回调函数,这是不是上下文async。 解释器可以防止我们

  • 我试图制作一个简单的应用程序来学习c(Visual Studio)中的一些东西。现在我正在制作一个音乐播放器,其中一个动作是在按钮点击事件中淡出音乐。 我对构建淡出部分没有问题,我做了一个while循环,每次循环运行时都将音量降低1%。此外,我还使用淡入度值更新标签。 唯一的问题是,为了减缓褪色,我正在使用线程。睡眠事件,该部分将冻结我的应用程序,并阻止使用淡入淡出值对我的文本标签进行任何更新。

  • 我试图获得适当的‘结构’来监控一个游戏的状态从外部源(s)使用(Tasks)async/await,以便在一个无限循环中运行任务,然而它的当前编写方式似乎只是冻结了我的UI。 到目前为止我得到的是: (在“状态机”类中) 如果没有上面的“task.delay”行,UI将完全冻结。使用“task.delay”行,它不会冻结,但是如果我试图拖动窗口,它会跳回到我开始拖动它的地方。 我对当前代码的假设是

  • 我有一个endpoint生成一些数据(需要一些时间),另一个endpoint可以用来获取生成的数据。我用wait调用第一个,从响应中获取id,并想调用第二个,而它的状态不是“Success”(它表示响应中准备和存储的数据),并继续我的脚本。 这是我的代码 它的工作,但我赢得了这么多的请求,我如何设置一些请求的间隔?我尝试使用await setInterval(),但是代码继续执行,没有等待结果 e

  • 问题内容: 我在node.js中有以下循环 UpdateDetail函数返回一个Promise。在继续循环的下一个迭代之前,我如何等待承诺解决/拒绝。 问题答案: 您可以为此使用异步库。然后转到async.eachSeries。 您需要先执行npm install async 这是示例: