0

I have a problem in my code where many entities have async loading procedures and can't be used until these are complete. There are chains of these dependencies. So A->B->C where A needs B needs C.

I have written code like

class B{
  constructor(callback){
    this.loaded=false
    this.load(callback)
  }
  load(callback){
    ...do stuff
    this.loaded=true
    callback()
  }
}

class A{
  constructor(){
    this.loaded=false
    this.b=new B(()=>{this.loaded=true})
  }
}

This seems really bad. Can anyone suggest a better solution?

Daniel
  • 379
  • 4
  • 15
  • 2
    Sounds like you probably want a factory method (at least) that can then more freely return Promises that resolve with an instance. So you'd be able to do `B.create().then(newInstance => /* do something */)`. Although that doesn't solve the whole async initialisation roundabout, at least it makes it behave normally, instead of having `new` produce async behaviour and modifying the internals of the class to pass around callbacks. – VLAZ Jan 27 '20 at 15:56

1 Answers1

0

Usually, it is a bad practice to perform async task directly in constructor (as stated here). With this taken in account, you can follow VLAZ advice and start using promises.

You would then have something like this:

class B {
  constructor() {
    this.loaded = false
  }

  load() {
    return new Promise((resolve =>  {
      this.loaded = true;
      // do stuff
      return resolve()
    }))
  }
}

class A {
  constructor() {
    this.loaded = false
  }

  load() {
    return new Promise(resolve => {
      this.b = new B()
      this.loaded = true
      return resolve(this.b)
    })
  }
}

// Use it like this
const a = new A()

a.load()
  .then(b => b.load())
  .then(/* and so on */)
jkoestinger
  • 980
  • 6
  • 8