你一般不想在構造函數中進行異步操作,因爲它創建複雜的對象,然後知道當異步操作已完成,或者由於您需要允許構造函數返回對象而導致錯誤,而不是承諾會在異步操作完成時告訴您。
有幾種可行的設計方案:
選項#1:不要在構造函數中做任何異步操作。然後,添加一個具有適當名稱的新方法,該方法執行異步操作並返回承諾。
就你而言,你可以使新方法成爲scan()
返回一個承諾。然後,通過創建它然後調用scan,然後使用返回的promise來知道數據何時有效,從而使用對象。
我不知道自己的打字原稿,所以我給你的代碼的修改版本,但概念是相同的兩種方式無論是打字稿或普通的JavaScript:
export class QueryAuthoriser {
authPerms: [AuthPerms];
constructor (data: string) {
}
scan() {
return AuthPermsDDB.scan().execAsync().then ((perms) => {
perms.Items.forEach(element => {
this.authPerms[element.name] = <AuthPerms> element.attrs
})
}).catch (err => {
console.log ('%%%%%%%%%%%%%% Err loading authPerms: ', err)
})
}
}
// usage
let obj = new QueryAuthoriser(...);
obj.scan(...).then(() => {
// the object is full initialized now and can be used here
}).catch(err => {
// error here
})
選項#2 :在構造函數中啓動異步操作,並在調用者的實例數據中使用承諾,以瞭解何時完成所有事情。
export class QueryAuthoriser {
authPerms: [AuthPerms];
constructor (data: string) {
this.initialScan = AuthPermsDDB.scan().execAsync().then ((perms) => {
perms.Items.forEach(element => {
this.authPerms[element.name] = <AuthPerms> element.attrs
})
}).catch (err => {
console.log ('%%%%%%%%%%%%%% Err loading authPerms: ', err)
})
}
}
// usage
let obj = new QueryAuthoriser(...);
obj.initialScan.then(() => {
// the object is full initialized now and can be used here
}).catch(err => {
// error here
});
選項#3:使用一個工廠函數,返回解析爲對象本身的承諾。
export createQueryAuthorizer;
function createQueryAuthorizer(...) {
let obj = new QueryAuthorizer(...);
return obj._scan(...).then(() => {
// resolve with the object itself
return obj;
})
}
class QueryAuthoriser {
authPerms: [AuthPerms];
constructor (data: string) {
}
_scan() {
return AuthPermsDDB.scan().execAsync().then ((perms) => {
perms.Items.forEach(element => {
this.authPerms[element.name] = <AuthPerms> element.attrs
})
}).catch (err => {
console.log ('%%%%%%%%%%%%%% Err loading authPerms: ', err)
})
}
}
// usage
createQueryAuthorizer(...).then(obj => {
// the object is fully initialized now and can be used here
}).catch(err => {
// error here
});
我的選擇是對選項#3有幾個原因。它捕獲工廠函數中的一些共享代碼,每個調用者必須在其他方案中執行該代碼。它也會阻止訪問對象,直到它被正確初始化。另外兩種方案只需要文檔和編程規則,很容易被濫用。
謝謝@ jfriend00,它很好用。雖然這段代碼會阻塞'createQueryAuthorizer'方法,而我的意圖是對數據庫進行異步調用,並且只等待第一次需要數據時,但只是第一次,因爲數據將需要多次。不過,我會嘗試改變實現。 –
@CarlosDelgado - 這裏沒有任何東西,所以我不太清楚你的意思。 'createQueryAuthorizer()'方法立即返回並返回一個promise。在正確初始化之前,您不能使用您的對象。如果代碼的其他部分也想使用同一個對象,他們可以等待相同的承諾。 – jfriend00