Based on your comments, you should probably do what every other HTMLElement with asset loading does: make the constructor start a sideloading action, generating a load or error event depending on the result.
Yes, that means using promises, but it also means "doing things the same way as every other HTML element", so you're in good company. For instance:
var img = new Image();
img.onload = function(evt) { ... }
img.addEventListener("load", evt => ... );
img.onerror = function(evt) { ... }
img.addEventListener("error", evt => ... );
img.src = "some url";
this kicks off an asynchronous load of the source asset that, when it succeeds, ends in onload
and when it goes wrong, ends in onerror
. So, make your own class do this too:
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);
And then you make the renderLoaded/renderError functions deal with the event calls and shadow 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', ...));
}
Also note I changed your id
to a class
, because unless you write some weird code to only ever allow a single instance of your <e-mail>
element on a page, you can't use a unique identifier and then assign it to a bunch of elements.
<e-mail data-uid="1028"></email>
and from there is populated with information using thecustomElements.define()
method. – Alexander Craggs.init()
to do the async stuff. Plus, since you're sublcass HTMLElement, it is extremely likely that the code using this class has no idea it's an async thing so you're likely going to have to look for a whole different solution anyway. – jfriend00