2017-09-28 124 views
1

我想填充我的var todos与我在我的Redis服务器,我得到,我必须使用承诺,但我可能不是在正确的地方。使用承诺和redis回调

首先,我得到所有ID为.smembers()函数,并为每个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); 
    }); 
}); 

回答

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)); 
+0

这promisify功能改变加载速度?我得到它看起来更好,但我仍然困惑为什么我会比以前的答案更好 –

+0

答案是**否**,_promisify_函数不会影响性能。正如你在例子中看到的,它返回一个简单的逻辑对象:'拒绝'承诺,当有错误,或'解析'异步调用的结果,否则。 – alexmac

1

如果要转换接受回调到返回一个承诺的功能异步功能,一般的方法是来包装功能的承诺,并通过由Promise构造函数的回调提供resolve

function getStuff(cb) { 
 
    setTimeout(() => cb('stuff'), 1000); 
 
} 
 

 
function withPromise() { 
 
    return new Promise(resolve => getStuff(resolve)); 
 
} 
 

 
withPromise().then(console.log);

这意味着,而不是把你的Redis的回调中承诺的创造,你应该将它出局它的IDE:

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