简体   繁体   中英

Node.js check value in a few redis sets and return synchronously

I have 7 sets and I need to check if value exists ( sismember ) at least in one set and return true or false.

I need to get that value synchronously, like this:

const isExist = !!(_.max(_.range(7).map((day) => {
    redis.sismember(`blacklist${day}`, hashToken, function (err, res) {
       return res;
    });
})));

You never want synchronous code when you can avoid it.

In this case I would recommend to use Promises in order to manage the seven requests to redis.

The 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 , so it's even "officially supported", if you care for that kind of thing.)

So what you seem to want is a function that checks up to seven asynchronous calls to sismember and resolves to an overal positive result as soon as the first of them has a positive result - Promise#any() can do that.

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

usage

checkBlacklist('some_token').then((result) => {
   // do something with the result
}).catch((err) => {
   // an error has occurred - handle it or rethrow it
});

If multiple redis ops are involved, generally I prefer to write lua script and then call it through my nodejs program. This is an unrelated example, but it shows how you can use lua through nodejs.

example: 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

NodeJS code that uses lua: say 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)
    })
  })
}

And, finally, a function that uses the cached sha digest to execute the script:

getJobState: function(jobId) {
    return loadScript('getState').then(function(hash) {
      return getConnection().then(function (conn) {
        return conn.evalshaAsync(hash, 1, jobId)
      })
    })
  },

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM