Basierend auf Ihren Kommentaren sollten Sie wahrscheinlich tun, was jedes andere HTMLElement mit dem Laden von Assets tut: Lassen Sie den Konstruktor eine Sideloading-Aktion starten, die je nach Ergebnis ein Lade- oder Fehlerereignis generiert.
Ja, das bedeutet Versprechungen zu verwenden, aber es bedeutet auch "Dinge genauso zu machen wie jedes andere HTML-Element", also sind Sie in guter Gesellschaft. Zum Beispiel:
var img = new Image();
img.onload = function(evt) { ... }
img.addEventListener("load", evt => ...);
img.onerror = function(evt) { ... }
img.addEventListener("error", evt => ...);
img.src = "some url";
diese weg tritt eine asynchrone Belastung der Quelle Vermögenswert, der, wenn es gelingt, in onload
endet und wenn es schief geht, endet in onerror
. Also, machen Sie Ihre eigene Klasse dies auch tun:
class EMailElement extends HTMLElement {
constructor() {
super();
this.uid = this.getAttribute('data-uid');
}
setAttribute(name, value) {
super.setAttribute(name, value);
if (name === 'data-uid') {
this.uid = value;
}
}
set uid(input) {
if (!input) return;
const uid = parseInt(input);
// don't fight the river, go with the flow
let getEmail = new Promise((resolve, reject) => {
yourDataBase.getByUID(uid, (err, result) => {
if (err) return reject(err);
resolve(result);
});
});
// kick off the promise, which will be async all on its own
getEmail()
.then(result => {
this.renderLoaded(result.message);
})
.catch(error => {
this.renderError(error);
});
}
};
customElements.define('e-mail', EmailElement);
Und dann machen Sie die renderLoaded/renderError Funktionen befassen sich mit dem Fall, Anrufe und Schatten dom:
renderLoaded(message) {
const shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.innerHTML = `
<div class="email">A random email message has appeared. ${message}</div>
`;
// is there an ancient event listener?
if (this.onload) {
this.onload(...);
}
// there might be modern event listeners. dispatch an event.
this.dispatchEvent(new Event('load', ...));
}
renderFailed() {
const shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.innerHTML = `
<div class="email">No email messages.</div>
`;
// is there an ancient event listener?
if (this.onload) {
this.onerror(...);
}
// there might be modern event listeners. dispatch an event.
this.dispatchEvent(new Event('error', ...));
}
Beachten Sie auch, änderte ich Ihre id
zu einem class
, denn wenn Sie nicht irgendeinen merkwürdigen Code schreiben, der nur eine einzige Instanz Ihres <e-mail>
Elements auf einer Seite erlaubt, können Sie keinen eindeutigen Bezeichner verwenden und ihn dann einer Reihe von Elementen zuweisen.
Zweck eines Konstruktors ist es, Ihnen ein Objekt zuzuordnen und dann sofort zurückzukehren. Kannst du viel genauer auf * genau warum * können Sie denken, dass Ihr Konstruktor async sein sollte? Weil wir hier fast garantiert mit einem [XY-Problem] umgehen können (https://meta.stackexchange.com/a/66378). –
@ Mike'Pomax'Kamermans Das ist durchaus möglich. Grundsätzlich muss ich eine Datenbank abfragen, um die Metadaten zum Laden dieses Elements zu erhalten. Das Abfragen der Datenbank ist eine asynchrone Operation, und daher muss ich darauf warten, dass dies abgeschlossen ist, bevor das Element erstellt wird. Ich würde Callbacks lieber nicht verwenden, da ich während des gesamten Rests des Projekts auf async/async gewartet habe und die Kontinuität beibehalten möchte. –
@ Mike'Pomax'Kamermans Der vollständige Kontext ist ein E-Mail-Client, in dem jedes HTML-Element ähnlich aussieht wie 'und von dort mit Informationen gefüllt wird mit den' customElements .define() 'Methode. –