Node.js 检查几个 redis 集合中的值并 return 同步
Node.js check value in a few redis sets and return synchronously
我有 7 个集合,我需要至少在一个集合中检查值是否存在 (sismember
) 并且 return true 或 false。
我需要同步获取那个值,像这样:
const isExist = !!(_.max(_.range(7).map((day) => {
redis.sismember(`blacklist${day}`, hashToken, function (err, res) {
return res;
});
})));
只要可以避免,就永远不需要同步代码。
在这种情况下,我建议使用 Promises 来管理对 redis 的七个请求。
Bluebird promise library can make most APIs promise-compatible in one line of code (read about promisification), the API of redis is no exception. (The documentation of Bluebird even uses redis as an example, and so does the node-redis documentation,所以它甚至 "officially supported",如果你关心那种事情。)
所以你似乎想要的是一个函数,它最多可以检查对 sismember
的七个异步调用,并在其中第一个有肯定结果时立即解析为总体肯定结果 - Promise#any() 可以做到。
var Promise = require('bluebird');
var _ = require('lodash');
var redis = require('redis');
Promise.promisifyAll(redis);
function checkBlacklist(hashToken) {
var blacklistChecks = _.range(7).map((day) => {
return redis.sismemberAsync(`blacklist${day}`, hashToken);
});
return Promise.any(blacklistChecks);
}
用法
checkBlacklist('some_token').then((result) => {
// do something with the result
}).catch((err) => {
// an error has occurred - handle it or rethrow it
});
如果涉及多个redis op,一般我更喜欢写lua脚本,然后通过我的nodejs程序调用。这是一个不相关的示例,但它显示了如何通过 nodejs 使用 lua。
示例:get_state.lua
local jobId = KEYS[1]
local jobExists = redis.pcall('exists', jobId)
if jobExists == 0 or jobExists == nil then
return 404 -- not found.
end
-- check the job state
local st = tonumber(redis.pcall('hmget', jobId, 'ctlState')[1])
if st == nil then
st = 12002 -- job running, unless explicitly stated otherwise
end
return st
使用 lua 的 NodeJS 代码:说 index.js
...
// List of script files
var scriptMap = {
getState: {file:'./scripts/get_state.lua'}
};
...
// A function to load the script file to Redis and cache the sha.
function loadScript(script) {
logger.trace("loadScript(): executing...");
if (scriptMap[script]['hash']) {
logger.trace("Sript already loaded. Returning without loading again...");
return Promise.resolve(scriptMap[script]['hash']);
}
//load from file and send to redis
logger.trace("Loading script from file %s...", scriptMap[script].file);
return fs.readFileAsync(scriptMap[script].file).then(function(data) {
return getConnection().then(function(conn) {
logger.trace("Loading script to Redis...");
return conn.scriptAsync('load', data)
})
})
}
最后,使用缓存的 sha 摘要执行脚本的函数:
getJobState: function(jobId) {
return loadScript('getState').then(function(hash) {
return getConnection().then(function (conn) {
return conn.evalshaAsync(hash, 1, jobId)
})
})
},
我有 7 个集合,我需要至少在一个集合中检查值是否存在 (sismember
) 并且 return true 或 false。
我需要同步获取那个值,像这样:
const isExist = !!(_.max(_.range(7).map((day) => {
redis.sismember(`blacklist${day}`, hashToken, function (err, res) {
return res;
});
})));
只要可以避免,就永远不需要同步代码。
在这种情况下,我建议使用 Promises 来管理对 redis 的七个请求。
Bluebird promise library can make most APIs promise-compatible in one line of code (read about promisification), the API of redis is no exception. (The documentation of Bluebird even uses redis as an example, and so does the node-redis documentation,所以它甚至 "officially supported",如果你关心那种事情。)
所以你似乎想要的是一个函数,它最多可以检查对 sismember
的七个异步调用,并在其中第一个有肯定结果时立即解析为总体肯定结果 - Promise#any() 可以做到。
var Promise = require('bluebird');
var _ = require('lodash');
var redis = require('redis');
Promise.promisifyAll(redis);
function checkBlacklist(hashToken) {
var blacklistChecks = _.range(7).map((day) => {
return redis.sismemberAsync(`blacklist${day}`, hashToken);
});
return Promise.any(blacklistChecks);
}
用法
checkBlacklist('some_token').then((result) => {
// do something with the result
}).catch((err) => {
// an error has occurred - handle it or rethrow it
});
如果涉及多个redis op,一般我更喜欢写lua脚本,然后通过我的nodejs程序调用。这是一个不相关的示例,但它显示了如何通过 nodejs 使用 lua。
示例:get_state.lua
local jobId = KEYS[1]
local jobExists = redis.pcall('exists', jobId)
if jobExists == 0 or jobExists == nil then
return 404 -- not found.
end
-- check the job state
local st = tonumber(redis.pcall('hmget', jobId, 'ctlState')[1])
if st == nil then
st = 12002 -- job running, unless explicitly stated otherwise
end
return st
使用 lua 的 NodeJS 代码:说 index.js
...
// List of script files
var scriptMap = {
getState: {file:'./scripts/get_state.lua'}
};
...
// A function to load the script file to Redis and cache the sha.
function loadScript(script) {
logger.trace("loadScript(): executing...");
if (scriptMap[script]['hash']) {
logger.trace("Sript already loaded. Returning without loading again...");
return Promise.resolve(scriptMap[script]['hash']);
}
//load from file and send to redis
logger.trace("Loading script from file %s...", scriptMap[script].file);
return fs.readFileAsync(scriptMap[script].file).then(function(data) {
return getConnection().then(function(conn) {
logger.trace("Loading script to Redis...");
return conn.scriptAsync('load', data)
})
})
}
最后,使用缓存的 sha 摘要执行脚本的函数:
getJobState: function(jobId) {
return loadScript('getState').then(function(hash) {
return getConnection().then(function (conn) {
return conn.evalshaAsync(hash, 1, jobId)
})
})
},