1
votes

Exécuter la fonction javascript après la fin de la précédente

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.


4 commentaires

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


5 Réponses :


0
votes

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.


3 commentaires

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.



3
votes

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 .


4 commentaires

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.



0
votes

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 * /)


0 commentaires

1
votes

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();
        });  
    }
}); 


0 commentaires

1
votes

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();
    });
});


1 commentaires

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