Access to a previously fulfilled promise leads to a chain of promises

What is the correct pattern for encoding with promises in order to access data coming from the system earlier into the promises chain?

For instance:

do_A.then(do_B).then(do_C).then(do_D).then(do_E_WithTheDataComingFrom_A_And_C_OnlyWhen_D_IsSuccesfullyCompleted) 

My current solution: going through a single JSON structure through a chain, and each step fills it. Any opinion on this?

+6
source share
2 answers

I do not think that there is one “correct” template for this. Your decision sounds neat, however it is a bit closely related. This might work just fine for your situation, but I see several problems with it as a general outline:

  • The steps involved must agree on the structure of the collector object.

  • Each step should be involved, at least in the transfer of the object, which may become tired if the chain is long, and the need for previous data occurs sporadically. It is also inflexible for entering steps not written by you (the chain is not always linearly executed).

  • They say differently: if do_A | B | C | D and do_E are under your control, you need to wrap them in a template to store your collector object in closure and convert to and from functions, natural inputs and results, since these functions will not "enter" your template.

  • On the other hand, if there are functions on it , then the dependencies between these steps are effectively hidden inside the functions. It may look clean, but it can become a maintenance problem. For example: if this is a team project, then someone might think that he can reorder your steps without having any hints in the tooltip about what do_E input will need.

I would suggest a simpler approach using closures:

 var a, c; do_A() .then(function(result) { a = result; return do_B(); }) .then(do_C) .then(function(result) { c = result; return do_D(); }) .then(function() { return do_E_WithTheDataComingFrom_A_And_C_OnlyWhen_D_Succeeds(a, c); }) .catch(failed); 

There is no collector object to define; do_A | B | C | D and do_E can be common functions without knowing any pattern; there is no template if the returned data (do_B and do_D) will not be used; and data dependencies (a and c) are explicit.

+3
source

Yes, this is the right way to associate state with actions.

Operations with the .then chain are very common and are usually our building block when circled around. It is in the very core of promises.

What you do is correct and idiomatic.


For a curious spirit will show it.

To verify this, we can check the promises specification.

We want to verify that:

  • He chains
  • In case of rejection, it does not call the handler in the chain, and then
  • He rejects the following promise returned from then for the same reason.
  • Executed in a return value sequence.

Check them out in order using the specification - specifically .then :

1. He's a chain

7.1, then it is necessary to return the promise [3.3].

Great, let him verify that he is also chaining at fullfillment

If either onFulfilled or onRejected returns x, run the promise resolution procedure> [[Resolve]] (prom2, x).

Great, therefore, we know that when our promise allows or rejects, then our then handler is called with the appropriate parameter. So .then(do_A).then(do_B) will always work if do_A allows.

2. If rejected, it does not call the handler in the chain, and then

7.iv. If onRejected is not a function and promise1 is rejected, then promise2 must be rejected for the same reason.

Great, so it rejects and calls onRejected if it is there, if it does not catch.

3. He rejects the following promise returned from then for the same reason.

We just looked at it in 2.

4. It performs the return value in the transmitting sequence.

It again

If either onFulfilled or onRejected returns x, run the promise resolution procedure [[Resolve]] (prom2, x).

So, if you install onFulfilled, it will start the resolution process. The resolution process itself dictates:

The procedure for resolving promises is an abstract operation that takes as a contribution a promise and a meaning that we designate as [[Decide]] (promise, x). If x is obscured, he tries to promise by accepting state x, on the assumption that x behaves at least as a promise. Otherwise, it fulfills a promise with a value of x.

If / when you call solvePromise with a value of y, run [[Resolve]] (promise, y).

Where y is the return value of x.

Excellent! therefore it works.

+2
source

Source: https://habr.com/ru/post/952048/


All Articles