将 promise 与 redis 回调一起使用
Using promise with redis callback
我正在尝试用我的 Redis 服务器中的内容填充我的 var todos
,我知道我必须使用承诺,但我可能不在正确的地方。
首先,我使用 .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);
});
});
如果要将接受回调的异步函数转换为returns promise 的函数,一般的做法是将函数包装在promise 中并传递resolve
Promise
构造函数作为回调:
function getStuff(cb) {
setTimeout(() => cb('stuff'), 1000);
}
function withPromise() {
return new Promise(resolve => getStuff(resolve));
}
withPromise().then(console.log);
这意味着,与其将 promise 创建放在您的 redis 回调中,不如将其移出它:
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();
});
});
});
问题是您创建的承诺不在正确的位置。它必须在 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));
我正在尝试用我的 Redis 服务器中的内容填充我的 var todos
,我知道我必须使用承诺,但我可能不在正确的地方。
首先,我使用 .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);
});
});
如果要将接受回调的异步函数转换为returns promise 的函数,一般的做法是将函数包装在promise 中并传递resolve
Promise
构造函数作为回调:
function getStuff(cb) {
setTimeout(() => cb('stuff'), 1000);
}
function withPromise() {
return new Promise(resolve => getStuff(resolve));
}
withPromise().then(console.log);
这意味着,与其将 promise 创建放在您的 redis 回调中,不如将其移出它:
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();
});
});
});
问题是您创建的承诺不在正确的位置。它必须在 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));