Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How promises and promise chaining works? [Problem with code]

I'm learning Node.js and trying to properly use the mysql2 module. Because of this, I have recently started researching about promises.

I'm writing a kind of "library", so I can practice all these topics, and while doing that, I got into a problem with promise chaining I can't really understand. Any help is well appreciated!

The problem is the following:

Let's say that I have a query function which fetches the database, process the data and returns a promise, so I can get that data and work with it in some other file.

Now, if I write my query function like this:


query(){
        let p = new Promise((resolve, reject) => {
            resolve("Hello world")
        });


        p.then(data => {
            console.log("Hello world a second time!");
        }).then(data => {
            console.log("Hello world a third time")
        })
        return p;
    }

and I try to "consume" that promise from other file like this:


DBObject.query().then((data) => {
    console.log("Hello world from the other file!");
})

Then the output is in the wrong order, the program prints this:

Hello world a second time!
Hello world from the other file!
Hello world a third time


On the other hand, if I change the code in the first file, and I don't try to separate promise chaining, like this:

query(){
        let p = new Promise((resolve, reject) => {
            resolve("Hello world")
        }).then(data => {
            console.log("Hello world a second time!");
        }).then(data => {
            console.log("Hello world a third time")
        })

        return p;
    }

It works just fine, and it prints:

Hello world a second time!
Hello world a third time
Hello world from the other file!

I don't understand this behaviour, I was thinking that declaring then blocks separately from the promise definition would be the same thing as do promise chaining right when I declare the promise, and it is clearly not like that!

Thanks beforehand for the answers you can give me. Also, It would be great if you could give me some suggestion on how to write code like this correctly. I mean, if I write code that uses promises, what should I return to the user? Another promise? Or just data for they to work with? I would really like writing code that follow the "standard" way of doing things.

Greets to you all! Thank you again.

like image 950
x_x Avatar asked Apr 08 '19 01:04

x_x


People also ask

What is the problem with promises in JavaScript?

Promises co-mingle rejected promises and unintended runtime exceptions. Apart from how the API is structured - promises have another major flaw: they treat unintentional native runtime exceptions and intentional rejected promises - which are two drastically different intentions - in the same "path".

How do you handle errors in promise chains?

There are two ways in which you can handle errors in your promise chain, either by passing an error handler to then block or using the catch operator.

What is promise chaining give an example?

Chaining after a catch It's possible to chain after a failure, i.e. a catch , which is useful to accomplish new actions even after an action failed in the chain. Read the following example: new Promise((resolve, reject) => { console. log("Initial"); resolve(); }) .


1 Answers

When you have one Promise, you can chain any number of Promises onto its .then. For example

const p = Promise.resolve();
p.then(() => console.log('then 1');
p.then(() => console.log('then 2');

means that p has two Promises that branch from it when it resolves: 1 and 2 (in addition to the promise p itself).

  p
 / \
/   \
1   2

What you're doing in your first code

let p = new Promise((resolve, reject) => {
  resolve("Hello world")
});
p.then(data => {
  console.log("second");
}).then(data => {
  console.log("third")
})
return p;

is like

"Hello world" = <Promise you return>
    |
    |
    |
  second
    |
    |
    |
  third = <unused Promise expression that the then chain resolves to>

You have two branches: the Promise you're returning resolves when Hello world runs, not when third runs.

On the other hand, when you call .then multiple times on a Promise, the whole expression evaluates to the Promise that resolves when the final .then runs:

let p = new Promise((resolve, reject) => {
  resolve("Hello world")
}).then(data => {
  console.log("Hello world a second time!");
}).then(data => {
  console.log("Hello world a third time")
})

return p;

is like

"Hello world"
     |
     |
'Hello second'
     |
     |
'Hello third' = <Promise you return>

where the returned Promise is the one that resolves right after Hello third runs.

like image 140
CertainPerformance Avatar answered Sep 20 '22 23:09

CertainPerformance