在嵌套 for 循环中获取值 - node.js、javascript、redis、Q 库
Getting values within a nest for-loop - node.js, javascript, redis, Q library
我正在尝试从嵌套的 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: " + 信息);
但我还没有找到一种方法来提取信息数组,使其具有 redisClient.hgetall() 函数之外的值。我已经尝试了 return 语句但无济于事,尽管作为一名初级程序员,我很有可能没有正确地执行这些语句。
注意:我已尝试从原始答案中获取指导,但我一定做错了什么,或者给出的解决方案不够好,或两者兼而有之。我已将 Q 库添加到我的项目中,并试图找到解决方案。这是我当前的代码:
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,回调将 always 运行 在代码执行后。
您有几种选择,包括使用 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
returns 一个函数,以便您可以干净地传递 info
数组,而无需定义每个内联函数。如果您更喜欢内联,那也可以。
我正在尝试从嵌套的 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: " + 信息);
但我还没有找到一种方法来提取信息数组,使其具有 redisClient.hgetall() 函数之外的值。我已经尝试了 return 语句但无济于事,尽管作为一名初级程序员,我很有可能没有正确地执行这些语句。
注意:我已尝试从原始答案中获取指导,但我一定做错了什么,或者给出的解决方案不够好,或两者兼而有之。我已将 Q 库添加到我的项目中,并试图找到解决方案。这是我当前的代码:
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,回调将 always 运行 在代码执行后。
您有几种选择,包括使用 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
returns 一个函数,以便您可以干净地传递 info
数组,而无需定义每个内联函数。如果您更喜欢内联,那也可以。