Слушатель событий Javascript - PullRequest
1 голос
/ 23 мая 2019

У меня есть 3 экземпляра класса Foo(). Давайте назовем их foo1, foo2 и foo3. По умолчанию isReady из Foo() равно false. В конструкторе Foo() есть асинхронный метод, который устанавливает isReady в true. Например, я мог бы быть setTimout с другой продолжительностью. После того, как я создаю эти 3 экземпляра, появляется функция: startMainAction(), которая должна вызываться только после foo1.isReady = true и foo2.isReady = true и foo3.isReady = true Принимая во внимание, что асинхронная функция не определена (это может быть случайная длительность), невозможно точно определить порядок, в котором экземпляры foo будут иметь свою собственность isReady, установленную на true. Следовательно, я не думаю, что мог бы использовать обратные вызовы для вызова startMainAction.

Как этого достичь?

 class Foo{
    
  constructor(n){
    this.isReady = false;
    setTimeout(()=>{
    this.isReady = true;
    console.log('I am ready '+n);
    }, Math.random()*1000)
  }
}
    
    
const foo1 = new Foo(1)
const foo2 = new Foo(2)
const foo3 = new Foo(3)
    
    
function startMainAction(){
    
    console.log('All fooes must be ready before I was called')
 }

Ответы [ 3 ]

0 голосов
/ 23 мая 2019

Вы можете добавить все свои экземпляры Foo в список, массив или все, что вы можете повторить.Затем сделайте что-нибудь вроде

let foos = [foo1, foo2, foo3];

function WaitUntilReady(callback) {
    let ready = true;
    foreach (let foo of foos) {
        if ( !foo.isReady ) {
            ready = false;
            break;
        }
    }

    if ( ready ) {
        callback(); 
    } else {
        setTimeout(WaitUntilReady, 100); //100 miliseconds until next check
    }
}

WaitUntilReady(function() {
    //every instance is ready
});

Редактировать: использование Promises кажется более изящным, не уверенным, действительно ли это так.Я не такой уж большой разработчик javascript, поэтому я даже не думал об их использовании

0 голосов
/ 23 мая 2019

Пусть метод конструктора создаст обещание, которое будет выполнено, когда произойдет условие для подготовки объекта.

Затем возьмите обещания от всех экземпляров и оберните их Promise.all, чтобы они ждали их всех.

class Foo {
  constructor() {
    this.isReady = false;
    this.isReadyPromise = new Promise( 
      res => setTimeout( 
        () => { console.log("I am ready"); this.isReady = true; res(true); },
        1000 + 1000 * (Math.floor(Math.random() * Math.floor(3)))
      )
    )
  }
}

const foo1 = new Foo(),
      foo2 = new Foo(),
      foo3 = new Foo();

Promise.all([ foo1.isReadyPromise, foo2.isReadyPromise, foo3.isReadyPromise ]).then(() => {
   console.log("All 3 are ready")
});
0 голосов
/ 23 мая 2019

Один из вариантов - добавить метод, который добавляет обратный вызов для вызова, если для isReady установлено значение true:

onReady(callback) {
  this.readyCallbacks.push(callback);
}

Затем, с этими тремя случаями, позвоните onReady с resolve Обещания и назовите Promise.all на этих трех Обещаниях:

const foos = [foo1, foo2, foo3];
Promise.all(foos.map(foo => new Promise(resolve => foo.onReady(resolve))))
  .then(startMainAction);

class Foo {
  constructor() {
    this.readyCallbacks = [];
    this.isReady = false;
    setTimeout(() => {
      this.isReady = true;
      console.log('I am ready');
      this.readyCallbacks.forEach(callback => callback());
    }, Math.random() * 1500)
  }
  onReady(callback) {
    this.readyCallbacks.push(callback);
  }
}

const foo1 = new Foo()
const foo2 = new Foo()
const foo3 = new Foo()
function startMainAction() {
  console.log('All fooes must be ready before I was called')
}
const foos = [foo1, foo2, foo3];
Promise.all(foos.map(foo => new Promise(resolve => foo.onReady(resolve))))
  .then(startMainAction);

Полагаю, вы могли бы также передать readyCallback в конструкторе, что привело бы к меньшему количеству кода, но это не совсем уместно, поскольку Foo (скажем, foo4), возможно, не нужно readyCallback, а readyCallback не необходим для создания экземпляра, это обработчик, который другие части кода запрашивают для добавления к экземпляру. (например, если у вас есть две части кода, которые должны были прослушивать isReady из foo1, вам понадобится что-то вроде этого onReady метода.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...