Promises hell/chaining promises in Javascript

  • Java
  • Thread starter shivajikobardan
  • Start date
  • Tags
    Javascript
In summary, the code in this block creates two promises, one to wait for 9s and the other to wait for 2s. When both promises have been resolved, the code in the block prints "order delivered".
  • #1
shivajikobardan
674
54
TL;DR Summary
asynchronous javascript
https://www.physicsforums.com/threa...-as-well-as-async-await.1048282/#post-6833326
My goal is to convert the callback hell in question to using promises.

The correct flow of program is:
Order created
Order received
Preparing food
Order ready
order delivered

The below code is wrong. If you put 9000 instead of 1000, the flow isn't correct.
JavaScript:
function createorder(timer = 0) {
  return new Promise(function (resolve) {
    setTimeout(resolve, timer);
  });
}

createorder(1000).then(() => {
      console.log('Order Created');
});

createorder(2000).then(() => {
      console.log('Order Received');
});

createorder(3000).then(() => {
  console.log('Preparing Food');
});

createorder(4000).then(() => {
  console.log('Order Ready');
});

createorder(5000).then(() => {
  console.log('Order Delivered');
});

But I fail to understand why it's wrong. Let's do a dry run of it:

Assume 9000 instead of 1000.

Wait 9s till the promise is resolved then "order created" gets printed.
Wait 2s till the promise is resolved then "order received" gets printed.
Wait 3s till the promise is resolved then "preparing food" gets printed.
Wait 4s till the promise is resolved then "order ready" gets printed.
Wait 5s till the promise is resolved then "order ready" gets printed.
I did it using promises hell and it's correct
JavaScript:
function createOrder(timer)
{
  return new Promise(function(resolve,reject){
    setTimeout(resolve,timer);
  })
}
createOrder(9000).then(function(){
  console.log("Order created");
  createOrder(1000).then(function(){
    console.log("order received");
    createOrder(1000).then(function(){
      console.log("preparing food");
      createOrder(1000).then(function(){
        console.log("order ready");
        createOrder(1000).then(function(){
          console.log("order delivered");
        })
      })
    })
  })
})

Dry run:

1) Wait 9s till promise is resolved, then print "order created".
then
2) Wait 1s till promise is resolved, then print "order received".
then
3) Wait 1s till promise is resolved, then print "preparing food".
then
4) Wait 1s till promise is resolved, then print "order ready".
then
5) Wait 1s till promise is resolved, then print "order delivered".
I must say I kinda get why this works (The "then".."then".."then".."then" makes it clear). But I don't understand why the first code block doesn't work.
I'm really finding it tough asynchronous javascript. I'm really out of ideas, and only a good analogy to learn can save me now.
 
Technology news on Phys.org
  • #2
PS the code copying feature doesn't seem to work in PF.
1671543008502.png
 
  • #3
shivajikobardan said:
Assume 9000 instead of 1000.

Wait 9s till the promise is resolved then "order created" gets printed.
Wait 2s till the promise is resolved then "order received" gets printed.
Wait 3s till the promise is resolved then "preparing food" gets printed.
Wait 4s till the promise is resolved then "order ready" gets printed.
Wait 5s till the promise is resolved then "order ready" gets printed.
My thoughts, with no convenient way to verify them, is that these calls to createOrder() aren't happening synchronously -- while the timer is running for the "order created" call, the other calls are executing. If my logic is correct, you would see "order received", "preparing food", and then "order ready" either before or after "order created".
 
  • #4
It's been, like, five years, which is five millennia in JavaScriptland but...

Doesn't nesting the promises defeat the whole purpose of asynch? The rationale of asynch the assumption that you can't count on any particular data arriving in time for other activities, If you force that, what's the point?
 
  • #5
DaveC426913 said:
It's been, like, five years, which is five millennia in JavaScriptland but...

Doesn't nesting the promises defeat the whole purpose of asynch? The rationale of asynch the assumption that you can't count on any particular data arriving in time for other activities, If you force that, what's the point?
Interesting instructor also used similar wordings like yours. Could you explain a bit more?
 
  • #6
shivajikobardan said:
Interesting instructor also used similar wordings like yours. Could you explain a bit more?
I remember having the same cognitive roadblock when learning: "Promises are The New Thing. Now, how do I cram them into my old, synchronous way of thinking?"

I think the question you need to ask yourself is: what are you trying to accomplish by using promises? Knowing that their very purpose is asynchrony, how are you using that to help your functionality?

At the risk of being glib, is it possible that you've been given a hammer and are concluding your app must be made of nails?I think we need to understand the parameters of the assignment before we can decide how to design it. For starters, is this a learning assignment or is it a real-world application?
 
Last edited:
  • #7
shivajikobardan said:
I don't understand why the first code block doesn't work.
It does work since it does exactly what you ask for.

You create a promise and ask to wait for 9s and then write "order created";

Then the code jumps to the next line - while the first promise is working asynchronously - where you ask to wait for 2s and then write "order received";

Then the code jumps to the next line - while the first and second promises are working asynchronously - where you ask to wait for 3s and then write "preparing food";

Then the code jumps to the next line - while the first, second, and third promises are working asynchronously - where you ask to wait for 4s and then write "order ready";

Then the code jumps to the next line - while the first, second, third, and fourth promises are working asynchronously - where you ask to wait for 5s and then write "order delivered";

All of this is done really fast (in the order of milliseconds) and all your promises are working together. Of course, they will resolve according to the time you set, so the text with the shortest time will appear first and the one with the longest time will appear last.

In the second example, you ask to do the next step only after the previous promise is resolved (activating the "then" function). So for the code to find out about the next promise to execute, it has to wait for the signal of the "parent" promise.
 
  • Like
Likes pbuk
  • #8
shivajikobardan said:
TL;DR Summary: asynchronous javascript

The below code is wrong.
Yes. That's because each call to createOrder returns immediately. That's what an async function does; it returns immediately, as soon as you call it, and the thing it returns is a promise, i.e., an object that represents an action that hasn't been completed yet. Caling .then on the return value of createOrder then also returns immediately, since .then is another async function that returns a promise.

So your "dry run" for this case is wrong. Here's what actually happens:

Set a timer that will go off in 9 seconds, and immediately return a promise that represents it; then call .then on this promise, which sets up a print statement to happen when the timer goes off, and immediately return an updated promise that represents that.

Do the same with 4 more timers and 4 more corresponding print statements.

All of this will return, and control flow will be at the bottom of your code block, before the first timer goes off. So what is actually controlling the order in which the print statements execute is the timing on the timers, not the order in which you make the function calls. The timers all start at basically the same time (since the time it takes to execute all of your code and return promises is negligible, much less than a second), so their timeouts control the order in which the timers go off and the print statements execute. And indeed that's what you're seeing.

In your second example, you are instead using repeated calls to .then to control the order in which the print statements execute, as well as using the timers to control the delays between them. That's why your "dry run" is correct for this case.
 
  • Like
Likes pbuk
  • #9
DaveC426913 said:
Doesn't nesting the promises defeat the whole purpose of asynch?
No. What it does is allow you to control the order in which certain things happen, while still taking advantage of the fact that, while those things are happening, your code can be doing something else. The real "async" that allows all that is happening deep inside the runtime engine, not anywhere in your code. That's why async code is often hard to reason about: because you can't see the actual control flow that is happening down in the runtime engine, where it is keeping track of all the async tasks that haven't completed and what each one is waiting on.
 
  • Informative
  • Like
Likes pbuk, berkeman and DaveC426913
  • #10

FAQ: Promises hell/chaining promises in Javascript

What are promises in Javascript?

Promises are objects in Javascript that represent the eventual completion or failure of an asynchronous operation. They allow us to write asynchronous code in a more readable and manageable way, by chaining together functions that will execute when the promise is resolved or rejected.

How do promises help with handling errors?

Promises have a built-in error handling mechanism that allows us to catch and handle errors that occur during the execution of a promise chain. This is done using the .catch() method, which will catch any errors that occur in the promise chain and allow us to handle them appropriately.

What is "chaining" promises in Javascript?

Chaining promises refers to the act of connecting multiple promises together, so that the result of one promise is used as the input for the next promise. This allows us to write cleaner and more organized code, and also makes it easier to handle asynchronous operations.

How do I create a promise in Javascript?

To create a promise in Javascript, we use the Promise constructor and pass in a function as an argument. This function takes in two parameters: "resolve" and "reject". Within this function, we can define the logic for our asynchronous operation, and then use the resolve and reject functions to either fulfill or reject the promise.

Can promises be used in both client-side and server-side Javascript?

Yes, promises can be used in both client-side and server-side Javascript. They are a part of the core language, so they can be used in any Javascript environment. They are commonly used in web development, both on the front-end and back-end, to handle asynchronous operations such as API calls and database queries.

Similar threads

Back
Top