Reputation:
I need the
event.target.innerHTML = FULL_HEART
event.target.setAttribute('class', 'like-glyph activated-heart')
after the displayError()
setTimeout interval is completed in the scenario that the mimicServerCall()
catches an error.
document.addEventListener('DOMContentLoaded', () => {
const likeButtons = document.querySelectorAll('.like-glyph');
const modal = document.getElementById('modal');
function displayError() {
modal.removeAttribute('class');
setTimeout(function(){ modal.setAttribute('class','hidden') }, 3000);
};
function likifyMe(button) {
button.addEventListener('click', (event) => {
if (event.target.innerHTML === EMPTY_HEART) {
mimicServerCall().then(() => {}).catch(() => {displayError()});
event.target.innerHTML = FULL_HEART
event.target.setAttribute('class', 'like-glyph activated-heart')
} else {
event.target.innerHTML = EMPTY_HEART
event.target.setAttribute('class', 'like-glyph')
}
});
};
likeButtons.forEach(button => {
likifyMe(button)
});
});
Is there a way to achieve this?
Upvotes: 0
Views: 209
Reputation: 2842
That's what a callback is for:
document.addEventListener('DOMContentLoaded', () => {
const likeButtons = document.querySelectorAll('.like-glyph');
const modal = document.getElementById('modal');
function displayError(callback) {
modal.removeAttribute('class');
setTimeout(function(){
modal.setAttribute('class','hidden');
callback();
}, 3000);
};
function likifyMe(button) {
button.addEventListener('click', (event) => {
if (event.target.innerHTML === EMPTY_HEART) {
mimicServerCall().then(() => {
event.target.innerHTML = FULL_HEART;
event.target.setAttribute('class', 'like-glyph activated-heart');
}).catch(() => {
displayError(function(){
event.target.innerHTML = FULL_HEART;
event.target.setAttribute('class', 'like-glyph activated-heart');
});
});
} else {
event.target.innerHTML = EMPTY_HEART
event.target.setAttribute('class', 'like-glyph')
}
});
};
likeButtons.forEach(button => {
likifyMe(button)
});
});
Upvotes: 1
Reputation: 11080
Leverage the following behavior of promise chaining detailed by MDN:
It's possible to chain after a failure, i.e. a catch, which is useful to accomplish new actions even after an action failed in the chain.
You can rewrite the block in question to this (notice it's .catch().then()
):
if (event.target.innerHTML === EMPTY_HEART) {
mimicServerCall().catch(() => displayError()).then(() => {
event.target.innerHTML = FULL_HEART;
event.target.setAttribute('class', 'like-glyph activated-heart');
});
} else {
Then, just have displayError()
return a promise that resolves with the timeout:
function displayError() {
return new Promise((resolve,reject) => {
modal.removeAttribute('class');
setTimeout(() => {
modal.setAttribute('class','hidden');
resolve();
}, 3000);
});
};
The resulting behavior is that your code to activate the heart is guaranteed to happen in the event of either success or failure, but if it did fail, it will wait the three seconds for the setTimeout
to execute. This is thanks to promise chaining, which will wait for the promise returned by displayError()
to resolve before executing the following .then()
callback.
Upvotes: 1