节点Redis异步

时间:2014-08-18 02:29:36

标签: node.js asynchronous redis

我有一个简单的函数tokenExists,它检查令牌是否已经是Redis set的一部分。我知道resp将以undefined的形式返回,因为最后一行代码在函数完成之前运行,并发出请求并从Redis获取响应。我已经阅读了许多关于使用async处理Redis Node性质的SO文章,但几乎所有这些文章都必须使用多行命令或Express和特定路径的问题。我想知道如何使这个代码同步。

function tokenExists(token, callback) {
  db.sismember("tokens", token, function(err,res) {
      if (err) throw err;
      callback(null, parseInt(res, 10) === 1);
  });
}

function generateToken(){
  try {
    var token = urlSafeBase64(crypto.randomBytes(23));
  } catch (ex) {
    console.log(ex)
  }
  tokenExists(token, function(err,res){
    if (err) throw err;
    res ? token : generateToken();
  })
}
^^ this method is returning 'undefined'

3 个答案:

答案 0 :(得分:0)

你不能。

数据库调用是异步的,因此您必须使用tokenExists函数的回调。

function tokenExists(token, callback) {
  db.sismember("tokens", token, function(err,res) {
      if (err) throw err;
      callback(null, parseInt(res, 10) === 1);
  });
}

答案 1 :(得分:0)

我不确定Javascript,这些是伪代码:

您可能希望以某种同步方式使用generateToken,如下所示:

void foo() {
  var token = generateToken();
  print(token);
  use(token);
}

但是你可能无法以某种方式使用它,如BarışUşaklı已经说过, 因为node.js只使用一个线程,并且可能不允许您阻止该线程。 因此,如果您想以异步方式使用它:

void foo() {
  generateToken(function(token) {
    print(token);
    use(token);
  });
}

您应该更改generateToken

function generateToken(callback){  // this line is changed.
  try {
    var token = urlSafeBase64(crypto.randomBytes(23));
  } catch (ex) {
    console.log(ex)
  }
  tokenExists(token, function(err,res){
    if (err) throw err;
    callback(res ? token : generateToken(callback));  // this line is changed.
  })

答案 2 :(得分:0)

使用异步代码,您必须完全接受延续模式。由于您使用redis呼叫进行了一次异步呼叫,因此您必须一直前往原始呼叫者。

您的代码修改了一下:

function tokenExists(token, callback) {
  db.sismember("tokens", token, function(err,res) {
      if (err) throw err;
      callback(null, parseInt(res, 10) === 1);
  });
}
//add an additional callack to generateToken
function generateToken(callback){
  try {
    var token = urlSafeBase64(crypto.randomBytes(23));
  } catch (ex) {
    console.log(ex)
  }
  //once this async call is made, you're off the main event loop.
  tokenExists(token, function(err,res){
  //standard node convention passes an error function as the first paramter
  //you can log it if you want,but let the callback know there was an error  
  if (err) return callback(err,null);
    if(res){
      return callback(null,res);
    }
    generateToken(callback);
  })
}

您必须从执行代码提供回调并在那里处理结果。以下是在快速路由回调中发送令牌的示例。如果您使用令牌执行更复杂的操作,例如保存记录(当然是异步),那么您将不得不在原始方法调用中管理多个回调。像Q或Bluebird这样的异步或承诺库等库可以提供帮助。您还可以查看callbackhell.com,了解如何使用命名方法和模块使用纯JavaScript进行操作。

//calling your generateToken
app.get('/token',function(req, res){
  generateToken(function(err, token){
    if(err) return res.send(500,err);
    res.end(token);
  })
});