2015-11-10 118 views
3

我知道this answer和下面的代碼是基於它。它正在工作,但我對某件事不滿意。Conditional on Promise.all

如果我想根據它進行一些有條件的檢查和解決該怎麼辦?我評論了我想要更改的代碼。

/** 
* Returns not yet propagate subdomains. 
* @return Promise 
*/ 
Tour.prototype.getOffline = function() { 
    var self = this; 
    var resolve_, reject_; 
    // to be fulfilled later 
    var promise = new Promise(function(resolve, reject){ 
    resolve_ = resolve; 
    reject_ = reject; 
    }); 

    var check = function(key) { 
    return new Promise(function(resolve, reject) { 
     redis_client.hmget(key, 'online', function(err, reply) { 
     if (reply[0] === 'n') { 
      resolve(key); // <----- I'd like to resolve only here 
     } else { 
      // reject(); // <---- I can't reject cause of Promise.all 
      resolve(); // <----- An empty value to satisfy Promise.all 
     } 
     }); 
    }); 
    }; 

    this.getKeysRedis('subdomain:*').then(function(resp) { 
    var promises = resp.map(check); 
    var results = Promise.all(promises); 
    results.then(function(data) { 

     // I have undefined values on data array 

     var array = data.filter(function(key){ 
     return utils.isDefAndNotNull(key); 
     }); 
     resolve_(array); // <------ How can I resolve without filtering 
    }); 
    }, function(error) { 
    reject_(error); 
    }); 
    return promise; 
}; 

最終代碼,刪除Promise構造反模式爲@Bergi提醒:

Tour.prototype.getOffline = function() { 
    var self = this; 

    var check = function(key) { 
    return new Promise(function(resolve, reject) { 
     redis_client.hmget(key, 'online', function(err, reply) { 
     if (reply[0] === 'n') resolve(key); 
     else reject(); 
     }); 
    }); 
    }; 

    var reflect = function(promise) { 
    return promise.then(
     x => ({state: 'resolved', value: x}), 
     e => ({state: 'rejected' , value: e}) 
    ); 
    }; 

    return new Promise(function(resolve, reject) { 
    self.getKeysRedis(self.subdomain_keyname + '*') 
    .then(function(keys) { 
     return Promise.all(keys.map(check).map(reflect)).then(function(r) { 
     return r.filter(x => x.state === 'resolved'); 
     }); 
    }) 
    .then(function(results) { 
     var array = results.map((result) => result.value); 
     resolve(array); 
    }) 
    .catch((err) => reject(err)); 
    }); 
}; 
+0

所以,你想在所有的承諾結清基本上做一個動作,不論是否達成或解決? (如果沒有,請[編輯]包括你想要做什麼,你在這裏的目標是什麼?) –

+0

我想我沒有得到你的問題。 –

+0

避免['Promise' constructor antipattern](http://stackoverflow.com/q/23803743/1048572)! – Bergi

回答

3

你基本上要一個函數,一個承諾,並返回滿足每當其他承諾做出決議(履行承諾或拒絕):

該功能通常稱爲「反映」:

function reflect(promise){ 
    return promise.then(x => ({state: "fulfilled", value: x}), 
         e => ({state: "rejected" , value: e})); 
} 

這意味着你可以拒絕(像通常那樣),然後執行:

this.getKeysRedis('subdomain:*').then(resp => 
    resp.map(check).map(reflect); // note the reflect 
).then(Promise.all).then(results => { 
    // access results here 
    results[0].state; // "fulfilled" if it fulfilled 
    results[0].value; // the value or error 
}); 
+0

這個'(x =>({state:「fulfilled」,value:x})'如何寫在javascript中?謝謝你的回答。 –

+3

@JonatasWalker呃.... that _is_ JavaScript。它運行在Node上我假定你正在使用 - 它是短(箭頭)函數語法,在這種情況下,你可以替換它爲'function(x){return {state:fulfilled,value:x};}'但它應該可以工作。 –