Дополнительно
Асинхронный/Ждут Конструктора Класса
На данный момент, я'м пытаясь использовать асинхронный/ждут внутри функции конструктора класса. Это значит, что я могу сделать пользовательский электронной почты тег для проекта Электрон я'м работает на.
customElements.define('e-mail', class extends HTMLElement {
async constructor() {
super()
let uid = this.getAttribute('data-uid')
let message = await grabUID(uid)
const shadowRoot = this.attachShadow({mode: 'open'})
shadowRoot.innerHTML = `
<div id="email">A random email message has appeared. ${message}</div>
`
}
})
Однако, на данный момент, проект не работает, со следующей ошибкой:
Class constructor may not be an async method
Есть ли способ обойти это, так что я могу использовать async/await не в этом? Вместо того, чтобы требовать обратных .тогда()?
108
13
Это может никогда работа.
В "асинхронный" по ключевым словам позволяет
ждут
, чтобы использоваться в функции, помеченные как "асинхронный", но он также преобразует функцию в генератор обещание. Поэтому функция помеченныеасинхронный
будет возвращать обещание. Конструктор с другой стороны возвращает объект строительства. Таким образом, мы имеем ситуацию, когда вы хотите вернуть объект и обещание: невозможная ситуация.Вы можете только использовать асинхронный/ждут, где вы можете использовать слово, потому что они по сути синтаксис сахара для обещаний. Вы можете'т использовать обещания в конструктор, потому что конструктор должен возвращать объект должен быть построен, а не обещание.
Есть две модели дизайна, чтобы преодолеть эту, как изобрели раньше обещания были вокруг.
init()
функция. Это работает немного как jQuery'ы.готов()
. Объект, который вы создаете, может быть использована только внутри это's собственноеinit
илиготов
функция:Использование:
значения var myObj = новый класс MyClass(); myObj.инициализации(функция() { // здесь можно использовать myObj });
Реализация:
класса MyClass { конструктор () {
}
инит (обратного вызова) { // сделать что-то async и вызвать обратного вызова: обратного вызова.привязать(это)(); } }
Использование:
класса MyClass.построить().потом(функция(myObj) { // myObj возвращает обещание, // не конструктор // или застройщика });
// с асинхронный/ждут:
асинхронные функции foo () { расчет var myObj = ожидайте класса MyClass.создать(); }
Реализация:
класса MyClass { конструктор (async_param) { если (typeof на async_param === 'не определено') { бросьте новую ошибку('не может быть вызван напрямую'); } }
статическая сборка () { возвращение doSomeAsyncStuff() .потом(функция(async_result){ возвращение нового класса MyClass(async_result); }); } }
Реализация асинхронных/ждут:
класса MyClass { конструктор (async_param) { если (typeof на async_param === 'не определено') { бросьте новую ошибку('не может быть вызван напрямую'); } }
статические асинхронные сборки () { ВАР async_result = ждут doSomeAsyncStuff(); возвращение нового класса MyClass(async_result); } }
Обратите внимание на вызов функции внутри статической функции.
Это не имеет ничего общего с async конструкторы, но с тем, что ключевое слово
это
на самом деле означает (что может быть немного удивительно для людей, приезжающих из языков, которые автоматически разрешение метода именами, то есть языков, которые Дон'т нужнаэто
ключевое слово).В
это
ключевое слово относится к созданному объекту. Не класса. Поэтому вы не можете нормально использовать " это " внутри статической функции после статической функции не привязаны к какой-либо объект, но и непосредственно привязана к классу.То есть, в следующем коде:
Вы не можете сделать:
вместо этого вы должны назвать его как:
Таким образом, следующий код приведет к ошибке:
Чтобы исправить это, вы можете сделать
бар
обычная функция или статический метод:Вы можете сделать это. В основном:
чтобы создать класс использования:
Примечание: Если вам нужно использовать супер, вы не можете назвать его в асинхронный обратный вызов. Вы называете это вне его это не 100% идеально, но на мой взгляд это очень идиоматические и я использую его все время в мой код.
На основе ваших комментариев, вы, вероятно, следует делать то, что любой другой объект HTMLElement с погрузкой актива: конструктор должен начать загрузку неопубликованных приложений действий, генерирующих нагрузку или ошибка в зависимости от результата.
Да, это означает, что, используя обещания, но это также означает "делать вещи таким же образом, как и любой другой HTML-элемент с", так что вы'вновь в хорошей компании. Например:
это стартует асинхронной загрузки исходного актива, что, когда это удастся, заканчивается на
события onload
и когда это случится, заканчивается вчисло
. Таким образом, сделать свой собственный класс сделать это слишком:И тогда вы сделаете функций renderLoaded/renderError реагировать на событие вызывает и тени Дом:
Также обратите внимание, я изменил свой ИД
в
класс, потому что, если вы пишете какой-то странный код, чтобы только один экземпляр в
<адрес электронной почты:>` элемент на странице, вы можете'т использовать уникальный идентификатор, а затем назначить его на кучу элементов.Ведь асинхронных функций обещания, можно создать статическую функцию в классе, который выполняет асинхронную функцию, которая возвращает экземпляр класса:
Звонок с
Пусть yql = ждут Yql.метод init()
от асинхронной функции.использование асинхронного метода в построении???
Я сделал этот тест-кейсов на основе @Downgoat'ы ответ. Она работает на NodeJS. Это Downgoat's код, где асинхронных часть обеспечивается
функции setTimeout()
вызов.Мой случай использования-это даос для серверной части веб-приложения. Как я вижу, даос, они каждый из которых связан с формат записи, в моем случае коллекции MongoDB, как например повар. В cooksDAO экземпляр держит повар's и данные. В мой беспокойный ум я хотел бы быть в состоянии создать экземпляр повар'с Дао, обеспечивающей cookId в качестве аргумента, и инстанцирование бы создать объект и заполнить его готовить's и данные. Таким образом, нужно запускать асинхронные вещи в конструкторе. Я хотел написать:
иметь такие свойства, Как готовить.getDisplayName()`. С этим решением я должен сделать:
который очень похож на идеал. Кроме того, мне нужно сделать это внутри функции "асинхронный".
Мой Б-план был покинуть загрузка данных из конструктора, основанные на внушении @slebetman для использования функции init, и сделать что-то вроде этого:
который не'т нарушать правила.
Если вы не "расширить", вы сможете избежать занятия все вместе и использовать композицию функций как constructors. Вы можете использовать переменные в области, а не члены класса:
Яш асинхронные построить функцию(...) { данные const = ждут принести(...); возвращение { данные: функция() { возврат данных; } } }
и просто использовать его в качестве
Яш const и А = ждут со многими(...);
Если вы'повторного использования TypeScript или поток, можно даже применить интерфейс constructors `` Интерфейс { данные: объект; }
асинхронные buildA0 функция(...): обещание<и> { ... } функция асинхронного buildA1(...): обещание<и> { ... } ... ``
Вы можете создать асинхронный метод init() {... вернуть; метод}
, то вместо этого нового класса MyClass().метод init()
всякий раз, когда вы'д, Как правило, просто сказатьновый класс MyClass()
.Это не чистый, потому что он опирается на всех, кто использует ваш код, и себя, всегда инстанцировать объект, как так. Однако, если вы'повторно только через этот объект в конкретном месте или два в коде, она должна быть тонкой.
Вы можете немедленно вызвать анонимный асинхронная функция, которая возвращает сообщение и установить его в переменную сообщение. Возможно, вы захотите взглянуть на тут же вызывается функция выражения (IEFES), в случае, если вы не знакомы с этой картиной. Это будет работать как шарм.
Вариация на шаблон строитель, с помощью call():
@slebetmen'ы принято отвечать хорошо объясняет, почему это не'т работу. Помимо двух моделей, представленных в ответ, другой вариант-доступ только для асинхронных свойства через пользовательский асинхронный геттер. Конструктор() может вызвать асинхронного создания свойства, а получатель проверяет, чтобы увидеть, если свойство доступно, прежде чем он использует и возвращает его.
Этот подход особенно полезен, когда вы хотите инициализировать глобальный объект сразу при запуске, и вы хотите сделать его внутри модуля. Вместо инициализации в index.js и передача экземпляра в тех местах, которые в ней нуждаются, просто требуют вашего модуля, где глобальный объект нужен.
Использование
Реализация
Вы должны добавить
, то функция к примеру. "Обещания" будут распознавать его как объект thenable с
обещание.разрешить автоматическиДругих ответов не хватает очевидного. Просто позвоните асинхронной функции из конструктора: