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

Моя HTML-страница:

<!DOCTYPE html>
<html>
  <head>
    <title>Foo</title>
    <script src="foo.js"></script>
  </head>
  <body>
    <p>Foo</p>
  </body>
</html>

Сценарий foo.js:

function onEvent1(callback) {
  console.log('registered callback for first event')
  setTimeout(callback, 1000)
}

function onEvent2(callback) {
  console.log('registered callback for second event')
  setTimeout(callback, 2000)
}

function work() {
  console.log('work done')
}

function main() {
  var event1Done = false
  var event2Done = false
  var windowLoadDone = false

  onEvent1(function () {
    event1Done = true
    console.log('first event done')
  })

  onEvent2(function () {
    event2Done = true
    console.log('second event done')
  })

  window = {}
  window.onload = function() {
    windowLoadDone = true
    console.log('window load done')
  }

  function workInvoker() {
    // check
    if (event1Done && event2Done && windowLoadDone) {
      work()
    } else {
      // retry
      setTimeout(workInvoker, 1000)
    }
  }

  workInvoker()
}

main()

Что я пытаюсь сделать: убедитесь, что work() работает только после трех произошли события: onEvent1, onEvent2 и window.onload.

Я реализовал onEvent1 и onEvent2 с setTimeout, но это может иметь любую реализацию, которая вызывает обратный вызов асинхронно.

Существует ли какая-либо концепция JavaScript, которая позволила бы мне убедиться, что work() автоматически вызывается после того, как три события происходят без меня жестко закодировать его с помощью механизма проверки и повтора, который я реализовал в workInvoker()

Ответы [ 3 ]

0 голосов
/ 31 октября 2018

Я начал писать именно то, что написал Феликс. Так что +1 к этому. : D Было бы короче с объектом поиска вместо локальных переменных, но это ручной подход.

Вы можете сделать то же самое более аккуратно с обещаниями, используя Promise.all, предполагая, что ваши обратные вызовы обещаны:

Promise.all(
  promiseOfEvent1,
  promiseOfEvent2,
  promiseOfWindowLoad
).then(results => {
  work();
})

, например,

const promiseOfWindowLoad = new Promise(function(resolve, reject) {
  window.onload = resolve;
});
0 голосов
/ 31 октября 2018

Вы можете использовать переменную-счетчик, которая увеличивается на 1 каждый раз, когда вызывается одна из трех функций. Когда значение счетчика достигает 3 u, то он может выполнить функцию work (), т.е. если counter == 3, то функция workInvoker () будет выполнена, а выполнить не будет.

OR Если вы хотите убедиться, что все три выполняются, вы можете использовать глобальный массив размером 3 и присвоить 0 всем трем значениям индекса. Присвойте 0,1,2 трем функциям, упомянутым выше, которые вы хотите выполнить. Если любая из этих функций называется u, то она может обновить свое соответствующее значение индекса в глобальном масштабе на 1. Затем, даже если ее вызвали несколько раз, оставьте значение индекса только как 1. Функция workInvoker () будет выполняться только тогда, когда все три значения индекса глобального массива равны 1, и вы можете использовать вспомогательную функцию, которая будет проверять значения индекса глобального массива.

0 голосов
/ 31 октября 2018

Просто позвоните workInvoker на каждое событие?

function main() {
  var event1Done = false
  var event2Done = false
  var windowLoadDone = false

  onEvent1(function () {
    event1Done = true
    console.log('first event done')
    workInvoker()
  })

  onEvent2(function () {
    event2Done = true
    console.log('second event done')
    workInvoker()
  })

  window = {}
  window.onload = function() {
    windowLoadDone = true
    console.log('window load done')
    workInvoker()
  }

  function workInvoker() {
    // check
    if (event1Done && event2Done && windowLoadDone) {
      work()
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...