使用redis回调的promise

时间:2017-09-28 15:16:33

标签: node.js asynchronous promise node-redis

我正在尝试使用我在Redis服务器中的内容填充var todos,我知道我必须使用promises,但我可能不在正确的位置。

首先,我使用.smembers()函数获取所有id,并且对于每个id,我获取具有正确id的对象并将其解析为todos

var todos=[];
res.locals.redis.smembers("todo:20", function(err, reply){ // i.e. SMEMBERS todo:20 returns 0 and 1
    var promises=reply.map(function(elem){

        res.locals.redis.get("todo:20:"+elem, function(err, reply1){ // i.e. GET todo:20:0
            return new Promise(function(resolve, reject){
                todos.push(JSON.parse(reply1));
                resolve();
            });
        });
    });

    Promise.all(promises)
    .then(function(){
        res.locals.redis.quit();
        res.render('todolist.ejs', {todo: todos});
    })
    .catch(function(reason){
        console.log(reason);
    });
});

2 个答案:

答案 0 :(得分:1)

如果要将接受回调的异步函数转换为返回promise的函数,通常的方法是将函数包装在promise中并传递function getStuff(cb) { setTimeout(() => cb('stuff'), 1000); } function withPromise() { return new Promise(resolve => getStuff(resolve)); } withPromise().then(console.log);构造函数提供的res.locals.redis.get("todo:20:"+elem, function(err, reply1){ // i.e. GET todo:20:0 return new Promise(...); // <-- move this outside of the callback }); 作为回调:

var promises = reply.map(function(elem){
  return new Promise(function(resolve, reject){
    res.locals.redis.get("todo:20:"+elem, function(err, reply1) {
      todos.push(JSON.parse(reply1));
      resolve();
    });
  });
});

这意味着,您不应将承诺创建放在redis回调中,而应将其移到其外部:

{{1}}

看起来像

{{1}}

答案 1 :(得分:1)

问题在于您创建的承诺不在正确的位置。它必须在map函数内部创建,而不是在redis.get回调函数内部创建:

res.locals.redis.smembers("todo:20", function(err, reply) {
  var promises = reply.map(function(elem) {
    return new Promise(function(resolve, reject) {
      res.locals.redis.get("todo:20:" + elem, function(err, reply1) {
        let todo = JSON.parse(reply1);
        resolve(todo);
      });
    });
  });

  Promise
    .all(promises)
    .then(function(todos) {
      res.locals.redis.quit();
      res.render('todolist.ejs', { todo: todos });
    })
    .catch(function(reason){
      console.log(reason);
    });
});

但更好的解决方案是创建 promisify 函数,并将所有回调式函数转换为promisified函数:

let promisify = (fn, params) {
  return new Promise((resolve, reject) => {
    fn(params, (err, res) => {
      if (err) {
        reject(err);
      } else {
        resolve(res);
      }
    });
  });
};

promisify(res.locals.redis.smembers, 'todo:20')
  .then(reply => {
    let promises = reply.map(elem => promisify(res.locals.redis.get, "todo:20:" + elem);
    return Promise.all(promises);
  })
  .then(results => {
    let todos = results.map(item => JSON.parse(item));
    res.locals.redis.quit();
    res.render('todolist.ejs', { todo: todos });
  })
  .catch(err => console.log(err));