J'ai la fonction "showElement" qui a un setTimeout. Comment puis-je faire que les appels à la fonction dans le eventListener du 'btnSend' s'exécutent les uns après les autres?
J'ai essayé avec .then () mais je n'ai pas fonctionné.
document.getElementById('btnSend').addEventListener('click', e => { e.preventDefault(); result = validateInputs(email, subject, message); if(result) { showElement(document.getElementById('formGroupSpinner'), 2000); showElement(document.getElementById('formGroupSuccessImg'), 2000); resetForm(); } }); //expects an html element and a number representing miliseconds. Shows the html element for that amount of time. function showElement(element, mSeconds) { element.classList.remove('d-none'); element.classList.add('d-block'); setTimeout( () => { element.classList.remove('d-block'); element.classList.add('d-none'); }, mSeconds); }
Les deux fonctions s'exécutent en même temps.
5 Réponses :
Le moyen le plus simple de faire ce que vous voulez est de changer simplement le deuxième showElement en 4000 au lieu de 2000 .
De cette façon, l'un aura un délai d'expiration de 2 secondes et l'autre de 4 secondes.
Ouais ça marcherait mais ça serait aussi très peu élégant
@ Sv443 tout ne doit pas être trop compliqué donc c'est "élégant"
Eh bien non seulement cela, mais c'est aussi plus peu fiable.
Il existe de nombreuses approches différentes, mais je suggère d'utiliser une promesse comme celle-ci:
document.getElementById('btnSend').addEventListener('click', e => { e.preventDefault(); var result = validateInputs(email, subject, message); if(result){ showElement(document.getElementById('formGroupSpinner'), 2000).then(()=>{ return showElement(document.getElementById('formGroupSuccessImg'), 2000); }).then(()=>{ resetForm(); }); } }); //expects an html element and a number representing miliseconds. Shows the html element for that amount of time. function showElement(element, mSeconds) { return new Promise((resolve, reject) => { element.classList.remove('d-none'); element.classList.add('d-block'); setTimeout( () => { element.classList.remove('d-block'); element.classList.add('d-none'); resolve(); }, mSeconds); }); }
En gros, la fonction après le .then ()
n'est exécutée qu'une fois que vous avez appelé le resolve();
.
Vous pouvez également utiliser un callback ou un async / await .
Cependant, vous voudrez désnnister vos puis
appels
@Bergi Je suis désolé mais je ne comprends pas ce que tu veux dire. Si c'est important, pouvez-vous modifier la réponse?
Pas aussi important que dans "ne fonctionne pas", mais c'est encore meilleur style. Édité.
Merci, après avoir essayé différentes approches, celle-ci a fonctionné pour moi.
Pour créer une chaîne de promesses, il faut d'abord avoir une promesse.
function showElement(element, mSeconds) { return new Promise(function(resolve,reject){ element.classList.remove('d-none'); element.classList.add('d-block'); setTimeout( () => { element.classList.remove('d-block'); element.classList.add('d-none'); resolve(); }, mSeconds); } }
Ensuite, vous pouvez utiliser showElement (). then (/ * quelque chose ici * /)
vous pouvez utiliser un rappel pour exécuter d'autres instructions après la fin de la fonction:
//First you add a param "callback" to the function function showElement(element, mSeconds, callback) { element.classList.remove('d-none'); element.classList.add('d-block'); setTimeout( () => { element.classList.remove('d-block'); element.classList.add('d-none'); //Then you ask if the callback function is present and call it if(callback && typeof callback === "function") callback(); }, mSeconds); } //Then use it in your event like this: document.getElementById('btnSend').addEventListener('click', e => { e.preventDefault(); result = validateInputs(email, subject, message); if(result) { showElement(document.getElementById('formGroupSpinner'), 2000, () => { showElement(document.getElementById('formGroupSuccessImg'), 2000); resetForm(); }); } });
Vous pouvez le faire en utilisant Promesse
. Vous devez envelopper votre fonction showElement ()
dans une promesse et appeler le résolveur de promesse une fois que setTimeout
se déclenche.
Ensuite, votre code d'appel peut canaliser
vos promesses avec puis
:
<button id="btnSend">Send</button> <div id="formGroupSpinner" class="d-none">Spinner</div> <div id="formGroupSuccessImg" class="d-none">Success image</div>
Cependant, cela conduit rapidement à l'enfer des rappels. P >
Vous pouvez éviter cela en utilisant asynchroniser / attendre
.
Vous marquez votre fonction comme async
, puis vous pouvez utiliser await
dedans pour attendre que les promesses se résolvent avant de passer à la suivante:
.d-none { display: none; } .d-block { display: block; }
Voici une démo fonctionnelle:
document.getElementById('btnSend').addEventListener('click', async e => { e.preventDefault(); await showElement(document.getElementById('formGroupSpinner'), 2000); await showElement(document.getElementById('formGroupSuccessImg'), 2000); }); function showElement(element, mSeconds) { return new Promise((resolve, reject) => { element.classList.remove('d-none'); element.classList.add('d-block'); setTimeout(() => { element.classList.remove('d-block'); element.classList.add('d-none'); resolve(); }, mSeconds); }); }
await showElement(document.getElementById('formGroupSpinner'), 2000); await showElement(document.getElementById('formGroupSuccessImg'), 2000); resetForm();
showElement(document.getElementById('formGroupSpinner'), 2000).then(() => { showElement(document.getElementById('formGroupSuccessImg'), 2000).then(() => { resetForm(); }); });
Merci, après avoir essayé différentes approches, celle-ci a fonctionné pour moi. Cependant j'ai fini par utiliser la solution fournie par Bergi
Bonjour Floro, vous semblez nouveau sur JS, recherchez les rappels JavaScript.
Veuillez également ajouter votre HTML :)
@jo_va pas pertinent
Pour utiliser
puis
, vous devez créer et renvoyer une promesse