У меня бывают ситуации, когда я бегаю async
код внутри class constructor
:
1. Запустите асинхронный код, который возвращает ответ.
Я выполняю некоторые async
код, который возвращает ответ, затем применяю then
и catch
внутри class constructor
:
class MyClass {
constructor(
someParameter,
anotherParameter,
) {
// Run async code that return a response
someAsyncCode()
.then( // do something with result of someAsyncCode )
.catch( // do something if someAsyncCode goes wrong )
}
}
2. Запустите асинхронный код, который не возвращает ответ.
В некоторых ситуациях async
код ничего не возвращает, но мне нужно его запустить.
class MyClass {
constructor(
someParameter,
anotherParameter,
) {
// Run async code that doesn't return anything
someAsyncCode()
}
async someAsyncCode() {
const someAsyncResult = await something();
// execute some other logic but not return anything
}
}
Вопросов
- Это хорошая или плохая практика, выполните некоторые
async
код внутриclass constructor
? - в ситуации, когда вам нужно выполнить
async
код, который ничего не возвращает, необходимо выполнитьthen
иcatch
? - каковы последствия выполнения
asyn
код безthen
иcatch
?
3 ответа
Хорошая или плохая практика — выполнять асинхронный код внутри конструктора класса?
Конструкторы всегда синхронны и должны немедленно создать объект. Если ваш асинхронный вызов не блокирует это и вас не волнует успех вашего асинхронного вызова, тогда неплохо вызвать функцию, не дожидаясь ее, и немедленно .catch
и обрабатывать любые возможные отказы.
В общем, если вам не нужно возвращаемое значение асинхронного вызова и вы не хотите ждать его завершения, вам не следует await
Это. Но вы все равно должны обрабатывать отказы с помощью .catch
; даже если вы ничего не делаете: something().catch(() => {})
в ситуации, когда нужно выполнить асинхронный код, который ничего не возвращает, нужно потом выполнить и поймать? каковы последствия выполнения асинхронного кода без then и catch?
Иметь then
не требуется и будет полезен только в том случае, если вы захотите что-то сделать после того, как обещание будет разрешено, но если обещание может быть отклонено, вы должны иметь catch
.
Если вы не поймаете отклоненное обещание, у вас будет unhandledPromiseRejection, который, если его не обработать, приведет к сбою вашего процесса в будущей версии Node.js.
Если вы позаботились о возвращаемом значении или хотите, чтобы вызывающая сторона могла обрабатывать отклонения, вы можете сделать конструктор закрытым, а затем добавить статическую асинхронную фабричную функцию, которая использует частный конструктор:
class MyClass {
private constructor(
someParameter,
anotherParameter,
) {
// No async calls here
}
static async create (
someParameter,
anotherParameter,
) {
await something();
return new MyClass(someParameter, anotherParameter);
}
}
Тогда вы бы использовали MyClass.create(x,y)
для его создания вместо new MyClass(x,y)
.
Задача конструктора — инициализировать экземпляр, то есть перевести его в определенное состояние. Использование (инкапсулированного) асинхронного кода может привести к тому, что экземпляр будет инициализирован только частично. Это приведет к тому, что экземпляр будет находиться в неопределенном состоянии и, следовательно, в коде, использующем его, который полагается на то, что экземпляр полностью инициализирован, чтобы выйти из строя непредсказуемо.
С другой стороны, если все внешние интерфейсы, то есть методы, свойства и т. Д., Которые демонстрирует класс, подчиняются любым, возможно, еще неразрешенным обещаниям асинхронного кода в конструкторе, этот эффект может быть смягчен и может применяться в очень особых случаях использования:
class Foo {
constructor () {
this.promise = asyncStuff();
}
get spamm () {
return await this.promise;
}
}
Однако это, скорее всего, приведет к очень сложному коду, который будет трудно поддерживать.
По указанным выше причинам я бы по возможности избегал использования асинхронного кода в конструкторах.
Вопросов.
«Это хорошая или плохая практика — выполнять асинхронный код внутри конструктора класса?»
Учебный класс constructor
функции не могут быть async
функции. Таким образом, объект, созданный с использованием constructor
(синтаксис класса) всегда немедленно возвращает объект.
Тогда это зависит от того, какой код вы ждете. Если этот код необходим для правильного функционирования созданного объекта, вы должны убедиться, что его поведение определяется состоянием обещания (данных или ошибок), которого он ожидает.
«в ситуации, когда вам нужно выполнить асинхронный код, который ничего не возвращает, необходимо выполнить его и поймать?»
Если обещание не возвращает результата, не выдает ошибок или завершение задачи не влияет отрицательно на состояние, тогда нет необходимости слушать его then
и catch
События.
«каковы последствия выполнения асинхронного кода без then и catch?»
Нет никаких последствий, если предположить, что не будет ошибок, с которыми нужно работать, или данных, которые нужно ожидать.