1

我需要一个异步包装器,用于由 db 查询备份的 redis 查询。如果redis查询失败,我想做db查询。如果db查询成功,我想在返回之前将返回的数据添加到redis中。我需要该函数(希望是对象上的几个此类方法之一)来返回一个承诺,因为它将在 node.js 中被调用。我正在使用蓝鸟承诺库,并使用它来承诺 redis。我正在为数据库使用 mongo-gyro,它也是基于蓝鸟的。这两个都独立工作。

任何帮助都深表感谢 - 甚至是伪代码 - 尤其是。错误处理

function get_something(key){
redis.get(key).done(function (res){
  if (null !== res){
    return res;  // how do I return a promise here?
  }
})
.done(function (res){
  db.find({'_id:key'}).done(function (res){
    if (null !== res){
      redis.set(key,result)  // set db value in redis
      .then(function(){
           return res;      //how do I return a promise here?
      })
    .catch()...?
    return res;  // how do I return a promise here?
    }
})
.catch...?

};

更新:下面的函数有效,最后显示来自 redis 或 mongo 的数据。但是 - 到目前为止,我一直未能成功地将其转换为类上的方法,该类返回要返回给 node.js 处理程序的承诺。注意 - 我需要添加“绑定”以捕获数据源

var oid = '+++++ test oid ++++++'
var odata = {
    'story': 'once upon a time'
}
var rkey = 'objects:'+ oid
redis.getAsync(rkey).bind(this).then(function(res){ 
  if(res === null){
    this.from = 'db'                            // we got from db
    return db.findOne('objects',{'_id':oid}) 
  }  
  data = JSON.parse(res)
  this.from = 'redis'                           // we got from redis
  return data
})
.then(function(res){    
  if(res !== null && this.from == 'db'){
    data = JSON.stringify(res)
    redis.setAsync(rkey,data)
  } 
  return res
})
.then(function(res){                           // at this point, res is not a promise
  console.log('result from ' + this.from)  
  console.log(res)                              
});
4

2 回答 2

1

.done终止一个承诺链。一般来说,Bluebird 足够聪明,可以自行处理未处理的拒绝。

.then您正在寻找的是:

redis.get(key).then(function(res){ res is redis .get response
     if(res === null) throw new Error("Invalid Result for key");
     return db.find({"_id":key); // had SyntaxError here, so guessing you meant this 
}).then(function(res){ // res is redis .find response
     return redis.set(key,result);
}).catch(function(k){ k.message === "Invalid Result for key",function(err){
   // handle no key found
});
于 2014-05-01T08:31:29.903 回答
1

Ideotype,根据我对您的原始问题和更新的理解,我相信您可以实现您的目标,而无需标记来跟踪哪个来源产生了所需的数据。

像这样的东西应该工作:

function get_something(oid) {
    var rkey = 'objects:' + oid;
    return redis.getAsync(rkey).then(function(res_r) {
        if (res_r === null) {
            return Promise.cast(db.findOne('objects', {'_id': oid})).then(function(res_db) {
                redis.setAsync(rkey, res_db).fail(function() {
                    console.error('Failed to save ' + rkey + ' to redis');
                });
                return res_db;
            });
        }
        return res_r;
    }).then(function (res) {//res here is the result delivered by either redis.getAsync() or db.find()
        if (res === null) {
            throw ('No value for: ' + rkey);
        }
        return res;
    });
}

笔记:

  • 您可能需要使用oid和修复线条rkey。我在这里的理解是有限的。
  • 这里的模式很不寻常,因为 mongo-gyro 查询是可选的,并且后续的 redis 更新对于整个函数的成功是学术性的。
  • 包装器可能是不必要的Promise.cast(),具体取决于db.findOne().
  • 毫无疑问,这将受益于对 Bluebird 有更好理解的人。
于 2014-05-02T22:36:27.890 回答