我正在尝试使用我在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);
});
});
答案 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));