resolving a promise with EventListener
You do not need to pass the promise to the event handler, you need to pass the resolve
callback:
function EventListenerForPopUp(resolve) {
this.removeEventListener("animationend", EventListenerForPopUp );
resolve();
}
// [...]
return new Promise(function(resolve, reject) {
this.Div.addEventListener("animationend", function() {
EventListenerForPopUp.call(this, resolve);
}, false);
This looks a bit ugly to me, maybe you can look at something like this:
var div = this.Div;
return new Promise(function (resolve) {
div.addEventListener("animationend", function animationendListener() {
div.removeEventListener("animationend", animationendListener);
//call any handler you want here, if needed
resolve();
});
});
Alternatively, we can create a reusable utility function as a means of creating a promise from any DOM event:
const createPromiseFromDomEvent = (eventTarget, eventName, run?) =>
new Promise((resolve, reject) => {
const handleEvent = () => {
eventTarget.removeEventListener(eventName, handleEvent);
resolve();
};
eventTarget.addEventListener(eventName, handleEvent);
try {
if (run) run();
catch (err) {
reject(err);
}
});
Example usage (with an MSE source buffer):
await createPromiseFromDomEvent(
sourceBuffer,
'update',
() => sourceBuffer.remove(3, 10)
);
Depending on the situation, the run
parameter may be needed to provide custom code to trigger the async operation (as above), or omitted if we know the operation has already started.
Another option is to abstract an externally controlled promise as a reusable function -
function thread () {
let resolve, reject
const promise = new Promise((res, rej) => {
resolve = res
reject = rej
})
return [promise, resolve, reject]
}
function customPrompt(form) {
const [prompt, resolve] = thread()
form.yes.addEventListener("click", _ => resolve(true), {once: true})
form.no.addEventListener("click", _ => resolve(false), {once: true})
return prompt
}
customPrompt(document.forms.myform)
.then(response => console.log("response:", response))
<form id="myform">
<input type="button" name="yes" value="yes" />
<input type="button" name="no" value="no" />
</form>
You can use async
and await
if you wanted -
async function main () {
const response = await customPrompt(document.forms.myform)
console.log("response:", response)
}
You could easily add a timeout by modifying customPrompt
-
function customPrompt(form) {
const [prompt, resolve, reject] = thread()
form.yes.addEventListener("click", _ => resolve(true), {once: true})
form.no.addEventListener("click", _ => resolve(false), {once: true})
// timeout after 30 seconds
setTimeout(reject, 30000, Error("no response"))
return prompt
}
For other creative uses of thread
, see this Q&A.