Выполнить функцию JavaScript после окончания предыдущего - PullRequest
0 голосов
/ 13 февраля 2019

У меня есть функция "showElement", которая имеет setTimeout.Как я могу сделать так, чтобы вызовы функции в EventListener 'btnSend' выполнялись один за другим?

Я пытался с .then (), но не работал.

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

Обе функции выполняются одновременно.

Ответы [ 5 ]

0 голосов
/ 13 февраля 2019

Вы можете сделать это, используя Promise.Вы должны обернуть свою функцию showElement() в обещание и вызвать распознаватель обещаний при срабатывании setTimeout.Тогда ваш код вызова может pipe ваши обещания вместе с then:

showElement(document.getElementById('formGroupSpinner'), 2000).then(() => {
    showElement(document.getElementById('formGroupSuccessImg'), 2000).then(() => {
        resetForm();
    });
});

Однако, это быстро приводит к аду обратного вызова.

Вы можете избежать этого, используя async/await.Вы помечаете свою функцию как async, затем вы можете использовать await внутри нее, чтобы дождаться разрешения обещаний, прежде чем переходить к следующему:

await showElement(document.getElementById('formGroupSpinner'), 2000);
await showElement(document.getElementById('formGroupSuccessImg'), 2000);
resetForm();

Вот рабочая демонстрация:

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);
  });
}
.d-none {
  display: none;
}

.d-block {
  display: block;
}
<button id="btnSend">Send</button>

<div id="formGroupSpinner" class="d-none">Spinner</div>
<div id="formGroupSuccessImg" class="d-none">Success image</div>
0 голосов
/ 13 февраля 2019

Вы можете использовать обратный вызов для выполнения других инструкций после завершения функции:

//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 голосов
/ 13 февраля 2019

Есть много разных подходов к этому, но я бы предложил использовать Обещание, как это:

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

В основном, функция после .then() выполняется только после того, как вы вызвали resolve();.

В качестве альтернативы вы также можете использовать обратный вызов или async / await .

0 голосов
/ 13 февраля 2019

Чтобы создать цепочку обещаний, сначала нужно иметь обещание.

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

Тогда вы можете использовать showElement().then(/*something here */)

0 голосов
/ 13 февраля 2019

Самый простой способ сделать то, что вы хотите, это просто изменить второй showElement на 4000 вместо 2000 .

Таким образом, одинбудет иметь тайм-аут 2 секунды, а остальные 4 секунды.

...