2016-08-18 21 views
1

我相信我理解基本形式的回調設計模式。然而,我不知道是否以及如何將這種設計模式應用於這種更復雜的情況。應用Node-JS的回調設計模式

我正在寫一組JavaScript函數用於服務器端。如果可能的話,這些函數必須返回從本地數據庫獲取的數據,否則返回來自外部API的數據。我想要做的是,在總結:

//dataProvider.js 
 
function DataProvider (dbCredentials, apiCredentials) { 
 
    DB = require('./dbStuff'); 
 
    API = require('./apiStuff'); 
 
    this.db = new DB(dbCredentials); 
 
    this.api = new API(apiCredentials); 
 
    
 
    this.getSpecificData = getSpecificDataWrapper(this.db, this.api); 
 
} 
 

 
function getSpecificDataWrapper(db, api) { 
 
    return function (extraQueryInfo) { 
 
    var result = db.genericGetFunc(specificDBQuery); 
 
    if (!satisfyingResult(result)) { 
 
     result = api.genericGetFunc(specificAPIQuery); 
 
    return result; 
 
    } 
 
}

當調用從主app.js文件這一功能,我想這樣做,因爲dataProviderInstance.getSpecificData(extraQueryInfo)。現在我有一個類似的結構設置爲執行查詢的數據庫和API函數。但由於這些查詢需要時間,所以getSpecificData總是返回undefined。

由於代碼在不同的文件中,使用這麼多回調會讓我瘋狂。那麼如何在這兩個或更多級別的函數調用中使用回調?

+2

您是否嘗試過使用[無極](https://developer.mozilla.org/en-US/ docs/Web/JavaScript/Reference/Global_Objects/Promise)在你的代碼中? – megapctr

回答

1

我會鼓勵你去承諾而不是回調。 回調的問題在於它最終會變得非常混亂。

對於你的問題一個非常好的解決方案將是這樣的。

//dataProvider.js 
 
function DataProvider (dbCredentials, apiCredentials) { 
 
    DB = require('./dbStuff'); 
 
    API = require('./apiStuff'); 
 
    this.db = new DB(dbCredentials); 
 
    this.api = new API(apiCredentials); 
 
    
 
    this.getSpecificData = getSpecificDataWrapper(this.db, this.api); 
 
} 
 

 
function getSpecificDataWrapper(db, api) { 
 
    
 
    return new Promise(function (resolve, reject) { 
 
    
 
    //I Assume that if this is an async operation, either receives a callback 
 
    //function or returns a promise. 
 
    db.genericGetFunc(specificDBQuery) 
 
     .then (function(result) { 
 
     if (satisfyingResult(result)) resolve(result) 
 
     
 
     // Again, I Assume that if this is an async operation, either receives a 
 
     //callback function or returns a promise. 
 
     else return api.genericGetFunc(specificAPIQuery); 
 
     }) 
 
     .then (function(result){ 
 
     resolve(result); 
 
     }) 
 
     .catch (function(err){ 
 
     reject(err); 
 
     }) 
 
    
 
    }); 
 
    
 
}

所以getSpecificData函數會返回一個承諾......你只需要鏈,然後等待結果

DataProvider.getSpecificData().then(function(result){ 
    //result will have your data 
}) 

希望這有助於!

+0

如果你使用藍鳥實現promise,你也可以使用'Promise.promisify(function)'而不是用'new Promise()'包裝你的函數。 http://bluebirdjs.com/docs/anti-patterns.html – winter

0

假設您的DB和API模塊也使用回調模式 ,那麼您應該使用 回調參數擴展getSpecificData()方法。這個回調方法,然後用 稱爲DB或以其他方式一個令人滿意的結果與API的結果:

function getSpecificDataWrapper(db, api) { 
    return function (extraQueryInfo, callback) { 
    db.genericGetFunc(specificDBQuery, function(result){ 
     if(satisfyingResult(result)){ 
     callback(result); 
     } 
     else { 
     api.genericGetFunc(specificAPIQuery, function(result){ 
      callback(result); 
     }); 
     } 
    }); 
    } 
} 

dataProviderInstance.getSpecificData(extraQueryInfo, function(result){ 
    // handle result here 
});