Код узла не блокируется?
У меня есть конструктор, который выбирает данные из DynamoDB, используя обещанные диногели для заполнения части свойств объекта. Таким образом, после создания экземпляра этого объекта свойство не заполняется, вот фрагмент кода:
export class QueryAuthoriser {
authPerms: [AuthPerms];
constructor (data: string) {
AuthPermsDDB.scan().execAsync().then ( (perms) => {
perms.Items.forEach(element => {
this.authPerms[element.name] = <AuthPerms> element.attrs
})
}).catch (err => {
console.log ('%%%%%%%%%%%%%% Err loading authPerms: ', err)
})
}
authFieldAccess (fieldName: string, args?:any): Promise<boolean> {
return new Promise ((resolve, reject) => {
console.log ('________________ authFieldAccess called for: ', fieldName)
console.log ('________________ this.authPerms entry: ', this.authPerms[fieldName])
resolve (true)
})
[...]
}
Так когда authFieldAccess
метод называется, поле this.authPerms
не определено Как я могу это исправить?
Спасибо, я изучаю ноды и набираю текст трудным путем:O
1 ответ
Как правило, вы не хотите выполнять асинхронную операцию в конструкторе, потому что это усложняет создание объекта, а затем знание того, когда асинхронная операция выполнена или если произошла ошибка, потому что вам нужно разрешить конструктору возвращать объект, а не обещание, которое сообщит вам, когда будет выполнена асинхронная операция.
Есть несколько возможных вариантов дизайна:
Вариант № 1: Не делайте никаких асинхронных операций в конструкторе. Затем добавьте новый метод с соответствующим именем, который выполняет асинхронную операцию и возвращает обещание.
В вашем случае вы могли бы сделать новый метод scan()
это возвращает обещание. Затем вы будете использовать свой объект, создав его и затем вызвав scan, а затем используя возвращенное обещание, чтобы узнать, когда данные действительны.
Я сам не знаю TypeScript, поэтому я дам измененную версию вашего кода, но концепция в любом случае одинакова, будь то TypeScript или обычный 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 по нескольким причинам. Он фиксирует некоторый общий код в заводской функции, который каждый вызывающий должен делать в других схемах. Это также предотвращает доступ к объекту, пока он не будет правильно инициализирован. Две другие схемы просто требуют документации и дисциплины программирования и могут легко использоваться неправильно.