事件监听器Javascript

时间:2019-05-23 11:37:08

标签: javascript dom-events

我有3个类Foo()的实例。我们称它们为foo1, foo2foo3。 默认情况下,isReady中的专有权Foo()false。在Foo()的构造函数中,有一个异步方法将isReady设置为true。例如,我可能是setTimout,但持续时间不同。在实例化这3个实例之后,有一个名为:startMainAction()的函数仅应在foo1.isReady = truefoo2.isReady = truefoo3.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 :(得分:0)

一个选项是添加一个方法,该方法将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的{​​{1}},则需要类似foo1的方法。 )

答案 1 :(得分:0)

让构造函数方法创建一个promise,该条件将在使对象准备就绪的条件发生时解决。

然后从所有实例中获取承诺,并用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")
});

答案 2 :(得分:-1)

您可以将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开发人员,所以我什至没有想到要使用它们