dimanche 23 avril 2017

How to avoid spaghetti code when using nested promises?

Say you have 6 methods that return promises, A(), B(), C(), D(), E(), F() and G().

Several of them cannot execute properly until others have. For instance, C() requires A(). F() & E() require C(). B() requires A() and F(). G() requires all others to be complete.

A().then(() => {
  C().then(() => {
    F().then(() => {
      B();
    });
    E();
  });
}).then(() => {
  G();
});
D();

Now, say that some logic needs to be run between several of these functions that affect their behavior.

A().then(() => {
  let foop = this._service.getFoop();
  C(foop).then((noop) => {
    noop.forEach((n) => { n *= -1; });
    F(noop).then((boop) => {
      boop = boop.flatten();
      B(foop, boop);
    });
    E('MonkeyWrench');
  });
}).then(() => {
  let glipglop = this._service.findGlip(this.LOCAL_GLOP_KEY);
  G(glipglop, 42);
});
D();

And then, on top of that, we need to make sure that each of these promises catches and handles errors.

A().then(() => {
  let foop = this._service.getFoop();
  C(foop).then((noop) => {
    noop.forEach((n) => { n *= -1; });
    F(noop).then((boop) => {
      boop = boop.flatten();
      B(foop, boop).catch((e) => {
        this.handleErrorB(e);
      });;
    }).catch((e) => {
      this.handleErrorF(e);
    });
    E('MonkeyWrench').catch((e) => {
      this.handleErrorE(e);
    });
  }).catch((e) => {
    this.handleErrorC(e);
  });
}).then(() => {
  let glipglop = _service.findGlip(this.LOCAL_GLOP_KEY);
  G(glipglop, 42);
}).catch((e) => {
  this.handleErrorA(e);
});
D().catch((e) => {
  this.handleErrorD(e);
});

So now we have a complete async program made up of promises - and it looks like a complete mess.

What is a way to take a program like this and make it easier to read so that future contributors can avoid diving into spaghetti code? Are nested promise structures inherently messy, or are there accepted protocols to clean this up and make it more readable?

I read http://ift.tt/1HoXyIN and it had some good ideas such as using promise.all([...]) to run multiple promises at once, but it didn't include any support for having logic between nested promise calls.

Thanks in advance to anyone willing to impart some wisdom for me on this.

Aucun commentaire:

Enregistrer un commentaire