草庐IT

javascript - 在嵌套 for 循环中获取值 - node.js、javascript、redis、Q 库

coder 2023-11-08 原文

我正在尝试从嵌套的 for 循环中提取值。我的循环从 Redis 获取值,我想将这些值添加到名为“info”的数组变量中。

重要的一点是 for 循环。

app.get('/query', function(req, res) {

    var info = [];

    redisClient.keys("todo:*", function(err, data) {            

        if (err) return console.log(err);

        for (var i = 0, len = data.length; i < len; i++) {
            var id = data[i];
            var listItem, author, goodness;

            redisClient.hgetall(data[i], function(err, obj) {
                listItem = obj.listItem;
                author = obj.author;
                goodness = {
                    id: id,
                    listItem: listItem,
                    author: author
                }
                info.push(goodness);
                console.log("In here: " + info);

            }); 
            console.log("Out here: " + info);
        }
        console.log("Way out here: " + info);
    }); 
    console.log("WAY THE HECK OUT HERE: " + info);
});

基本上,我希望将变量“goodness”中的值推送到名为“info”的数组变量中。当我执行代码时,信息数组会在这里填满,

console.log("In here: " + info);

but I have not found a way to extract the info array to have values outside of the redisClient.hgetall() function. I have tried return statements to no avail, though as a beginning programmer there is a decent chance I'm not doing these properly.

NOTE: I have tried to take guidance from the original answer and I must be doing something wrong, or the solution given wasn't good enough, or both. I have added the Q library to my project, and have tried to find a solution. Here is my current code:

app.get('/query', function(req, res) {

    var redisKeys = Q.nbind(redisClient.keys, redisClient);
    var redisHGetAll = Q.nbind(redisClient.hgetall, redisClient);
    var id, listItem, author;

    var info = [];

    redisKeys('todo:*').then(function (data) {
        console.log("First: " + data);
       var QAll = Q.all(data.map(processKeysFunc(info)));
       console.log("Reading within this: " + data);
       console.log("Next within this: " + QAll);
    }, function (err) { 
        if (err) return console.log(err);
        }).then(function () {
       console.log("Finally: " + data);

    })();

    function processKeysFunc(array) {
        return function (key) {
            console.log("This is the key: " + key);
            return redisHGetall(key).then(function (obj) {
                console.log("This is the obj: " + obj);
                array.push({
                    id: obj.id,
                    listItem: obj.listItem,
                    author: obj.author
                });
            });
        };
    }
});

这是我在 console.log 中得到的:

First: todo:281f973d-6ffd-403b-a0f4-9e8958caed35,todo:7ed8c557-0f15-4555-9119-
6777e1c952e8,todo:eb8dbee1-92ca-450e-8248-ad78548cd754,todo:712e8d27-bf9b-46f0-bfdd-
c53ef7d14441,todo:301dd91a-2b65-4b87-b129-a5ad569e38e5,todo:720d98b8-bdec-446d-a178-
fb7e264522aa,todo:d200c6cf-2ee5-443b-b7dc-d245c16899c8,todo:8169e9af-0204-42c8-9ddf-
3b00f7161b11

This is the key: todo:281f973d-6ffd-403b-a0f4-9e8958caed35

最佳答案

node.js 通常是非阻塞的,这就是使用回调的原因。传递给 .hgetall 的回调只会在完全接收到来自 redis 的数据时执行。它周围的其余代码将立即执行,而不是等待来自 redis 的数据。事实上,由于 .hgetall 调用可能涉及 IO,因此回调将始终在周围代码执行后运行。

您有几种选择,包括使用 Promises ( https://github.com/kriskowal/q )。

我将建议一个解决方案,该解决方案应该可以理解您的代码的当前结构:

app.get('/query', function(req, res) {

    var info = [];
    var completed = 0;

    redisClient.keys("todo:*", function(err, data) {            

        if (err) return console.log(err);

        for (var i = 0, len = data.length; i < len; i++) {
            var id = data[i];
            var listItem, author, goodness;

            redisClient.hgetall(data[i], function(err, obj) {
                completed++;
                if (err) return console.log(err);

                listItem = obj.listItem;
                author = obj.author;
                goodness = {
                    id: id,
                    listItem: listItem,
                    author: author
                }
                info.push(goodness);
                console.log("In here: " + info);

                if (completed === data.length) {
                    // Do something with info here, all work has finished
                }

            }); 
            console.log("Out here: " + info);
        }
        console.log("Way out here: " + info);
    }); 
    console.log("WAY THE HECK OUT HERE: " + info);
});

关键位是新变量 completed,它跟踪返回了多少回调。

不过,我强烈建议改用 promises。像这样的东西:

var Q = require('q');

var redisKeys = Q.nbind(redisClient.keys, redisClient);
var redisHGetall = Q.nbind(redisClient.hgetall, redisClient);

app.get('/query', function(req, res) {
    var info = [];
    redisKeys('todo:*').then(function (data) {
        return Q.all(data.map(processKeysFunc(info));
    }, function (err) { /* handle error */ }).then(function () {
       console.log('Complete info array=%j', info);
       res.setHeader('Content-Type', 'application/json');
       res.end(JSON.stringify(info));
    });
});

function processKeysFunc(array) {
    return function (key) {
        return redisHGetall(key).then(function (obj) {
            var goodness = {
                id: key,
                listItem: obj.listItem,
                author: obj.author
            };
            array.push(goodness);
        });
    }
}

processKeysFunc 返回一个函数,以便您可以干净地传递 info 数组,而无需定义每个内联函数。如果您更喜欢内联,那也行。

关于javascript - 在嵌套 for 循环中获取值 - node.js、javascript、redis、Q 库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27778042/

有关javascript - 在嵌套 for 循环中获取值 - node.js、javascript、redis、Q 库的更多相关文章

  1. ruby-on-rails - Rails 编辑表单不显示嵌套项 - 2

    我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib

  2. ruby - 将散列转换为嵌套散列 - 2

    这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[

  3. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  4. ruby-on-rails - Rails 中的 NoMethodError::MailersController#preview undefined method `activation_token=' for nil:NilClass - 2

    似乎无法为此找到有效的答案。我正在阅读Rails教程的第10章第10.1.2节,但似乎无法使邮件程序预览正常工作。我发现处理错误的所有答案都与教程的不同部分相关,我假设我犯的错误正盯着我的脸。我已经完成并将教程中的代码复制/粘贴到相关文件中,但到目前为止,我还看不出我输入的内容与教程中的内容有什么区别。到目前为止,建议是在函数定义中添加或删除参数user,但这并没有解决问题。触发错误的url是http://localhost:3000/rails/mailers/user_mailer/account_activation.http://localhost:3000/rails/mai

  5. ruby - 简单获取法拉第超时 - 2

    有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url

  6. ruby - 从 Ruby 中的主机名获取 IP 地址 - 2

    我有一个存储主机名的Ruby数组server_names。如果我打印出来,它看起来像这样:["hostname.abc.com","hostname2.abc.com","hostname3.abc.com"]相当标准。我想要做的是获取这些服务器的IP(可能将它们存储在另一个变量中)。看起来IPSocket类可以做到这一点,但我不确定如何使用IPSocket类遍历它。如果它只是尝试像这样打印出IP:server_names.eachdo|name|IPSocket::getaddress(name)pnameend它提示我没有提供服务器名称。这是语法问题还是我没有正确使用类?输出:ge

  7. Ruby——嵌套类和子类是一回事吗? - 2

    下面例子中的Nested和Child有什么区别?是否只是同一事物的不同语法?classParentclassNested...endendclassChild 最佳答案 不,它们是不同的。嵌套:Computer之外的“Processor”类只能作为Computer::Processor访问。嵌套为内部类(namespace)提供上下文。对于ruby​​解释器Computer和Computer::Processor只是两个独立的类。classComputerclassProcessor#Tocreateanobjectforthisc

  8. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

  9. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  10. ruby-on-rails - 获取 inf-ruby 以使用 ruby​​ 版本管理器 (rvm) - 2

    我安装了ruby​​版本管理器,并将RVM安装的ruby​​实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby​​。有没有办法让emacs像shell一样尊重ruby​​的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el

随机推荐