2017-09-28 175 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(); 
    }); 
    }); 
});