Как выполнить функцию последовательно или синхронно - PullRequest
0 голосов
/ 13 сентября 2018

У меня есть 4 функции, которые я хочу выполнить последовательно.

В частности, 4-я функция должна выполняться только после завершения всех трех предыдущих функций.

Я пытался использовать обратные вызовы, но дляуверен, что я не использую это правильно.Как мне сделать это последовательно.

Я слышал о функции then в JavaScript, но похоже, что она работает только с ECMAScript 6 (не уверен), но когда я пытаюсь использовать ее в своем скрипте, появляется неопределенная ошибка.

function longRunningFunction(callBack) {

  setTimeout(function() {
    $('#div1').html('Div1 Done');
  }, 5000);
  setTimeout(function() {
    $('#div2').html('Div2 Done');
  }, 5000);
  setTimeout(function() {
    $('#div3').html('Div3 Done');
  }, 5000);

  callBack();

}
longRunningFunction(function() {
  setTimeout(function() {
    $('#div4').html('But changes 1st!');
  }, 3000);
});
#div4 {
  font-weight: bold;
  color: red;
}

#div1 {
  margin-top: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="div4">
  My content should be changes at last!
</div>
<div id="div1">
  Div1
</div>
<div id="div2">
  Div2
</div>
<div id="div3">
  Div3
</div>

Ответы [ 4 ]

0 голосов
/ 13 сентября 2018

Вы можете использовать Обещания, как сказал другой ответ. Но если вы думаете, что это слишком много «тяжелой техники» для такого простого варианта использования (который, возможно, так и есть), вы можете просто установить флаг для каждого успешного тайм-аута, а затем запустить обратный вызов, когда все установлены. Ниже приведен один из способов:

function longRunningFunction(callBack) {

  var done = [false, false, false];

  function checkIfDone(cb) {
    if (done[0] && done[1] && done[2]) {
      cb();
    }
  }

  setTimeout(function() {
    $('#div1').html('Div1 Done');
    done[0] = true;
    checkIfDone(callBack);
  }, 5000);
  setTimeout(function() {
    $('#div2').html('Div2 Done');
    done[1] = true;
    checkIfDone(callBack);
  }, 5000);
  setTimeout(function() {
    $('#div3').html('Div3 Done');
    done[2] = true;
    checkIfDone(callBack);
  }, 5000);
}
longRunningFunction(function() {
  setTimeout(function() {
    $('#div4').html('But changes 1st!');
  }, 3000);
});
0 голосов
/ 13 сентября 2018

Вы можете попробовать генераторы

function* generateSequence() {
  yield 1;
  yield 2;
  return 3;
}

let generator = generateSequence();

let one = generator.next();

alert(JSON.stringify(one)); // {value: 1, done: false}
0 голосов
/ 13 сентября 2018

У вас есть x4 функции для setTimeout, так что вы можете комбинировать простую функцию с обещаниями и асинхронными / ожидающими функциями:

Просто замените () => console.log() на () => $('#div1').html('Div1 Done');

function sequentialTimeout(time, func){
  return new Promise(resolve => setTimeout(() => resolve(func()), time));
}

async function sequence(){
  await sequentialTimeout(500, () => console.log('1'))
  await sequentialTimeout(500, () => console.log('2'))
  await sequentialTimeout(500, () => console.log('3'))
  sequentialTimeout(500, () => console.log('4'))
}

sequence()
0 голосов
/ 13 сентября 2018

Вы можете использовать Promises для достижения этого.
Установите обещание для каждого асинхронного изменения и дождитесь его выполнения с помощью Promise#all:

Promise.all([p1, p2, p3]).then(() => {
  callBack();
});

Демо:

function longRunningFunction(callBack) {

  let p1 = new Promise((resolve, reject) => {
    setTimeout(function() {
      $('#div1').html('Div1 Done');
      resolve();
    }, 5000);
  });

  let p2 = new Promise((resolve, reject) => {
    setTimeout(function() {
      $('#div2').html('Div2 Done');
      resolve();
    }, 5000);
  });

  let p3 = new Promise((resolve, reject) => {
    setTimeout(function() {
      $('#div3').html('Div3 Done');
      resolve();
    }, 5000);
  });

  Promise.all([p1, p2, p3]).then(() => {
    callBack();
  });
}
longRunningFunction(function() {
    $('#div4').html('But changes 1st!');
});
#div4 {
  font-weight: bold;
  color: red;
}

#div1 {
  margin-top: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="div4">
  My content should be changes at last!
</div>
<div id="div1">
  Div1
</div>
<div id="div2">
  Div2
</div>
<div id="div3">
  Div3
</div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...