2016-03-07 120 views
0

我正在創建一個類,它從數據庫中檢索信息並適當地設置用戶變量。在Javascript中是一個異步類是一個好主意嗎?

我的問題是,我使用的數據庫API是異步的,這成爲一個問題,因爲該類在「完全構造」(也就是說構造函數已返回)之前變得可訪問。

所需的同步方法

class User{ 
    constructor(sql){ 
     this.name = Database.selectQuery(sql); 
    } 
} 
var x = new User(statement); 
console.log(x.name); // returns name 

當前異步方法

class User{ 
    constructor(sql){ 
     Database.selectQuery(sql, this, function(data, obj){ 
      obj.name = data; 
     }); 
    } 
} 
var x = new User(statement); 
console.log(x.name); // returns undefined 

我知道我可以在回調添加到我的構造,以使其異步工作,但此一個好主意?

+0

如果您在節點中編寫代碼,則正在編寫異步代碼。您正在使用回調或承諾。 –

+0

歡迎來到「回撥地獄」。 –

回答

2

您很快就會發現,所有異步操作必須能夠在完成後與調用者通信,因爲他們將來會完成一些不確定的時間。這意味着他們或者需要接受回調,或者他們需要返回一個承諾。

雖然可以將回調傳遞給構造函數,但不能從構造函數返回承諾(它必須返回對象),因此通常不建議在構造函數中放置異步操作。相反,調用者的代碼流更直接,如果你構造對象並且THEN調用對象上的異步方法。

如您的示例清楚地顯示的那樣,您創建的對象User的調用者無法知道構造函數中的異步操作何時完成,因此調用者沒有可靠的方式來使用該對象的結果操作。這不僅僅是一個壞主意,而是一個完整的非首發。你可能會迫使調用者設置某種超時,並猜測異步操作完成或者查找完成時 - 這些都是不好的事情。

比較常見的設計方法是將異步操作分離出來,進入一個方法:

class User{ 
    constructor(){ } 

    select(sql, callback) { 
     Database.selectQuery(sql, this, function(data, obj){ 
      obj.name = data; 
      callback(); 
     }); 
    } 

} 

var x = new User(); 
x.select(statement, function() { 
    console.log(x.name); 
}); 

設計異步接口的現代生活方式是真的動諾言,現在,他們在錯誤處理和提供顯著優勢協調多個異步操作,這實際上是我對接口的建議。

上面的界面可能還需要錯誤處理。

+0

感謝您的回覆。請忽略缺少錯誤處理 - 所提供的代碼被簡化以高效地表達我的問題。 爲了進一步討論,無論我創建異步構造函數還是單獨的函數,我仍然有同樣的問題。我將不得不把我的整個程序代碼放在回調中。 用戶類應該是存儲在服務器上的內容的緩存版本,並將傳遞給視圖。如果我使用回調,我無法看到如何將它傳遞給視圖。 – Andy

+0

@Andy - 歡迎來到node.js中的異步編程。是的,您必須將所有希望使用異步操作結果的代碼放入完成回調函數或從此處調用的函數中。這就是異步編程在Javascript中的工作原理。你需要使用這個概念。您的設計可能需要進行調整,因此對象不會嘗試使用異步操作進行初始化,因爲該設計模式只是有問題。 – jfriend00

相關問題