Olivier.B
Olivier.B

Reputation: 109

Promise Chaining same function

i want to create a fake discussion in JS with promises.

console.log wait X seconds,
console.log wait X seconds ...

Here is my code:

var addMessage = function (msg) {
  return new Promise(function (resolve, reject) {
    setTimeout( function() {
      console.log(msg)
      resolve()
    }, 2500)
  })
}

var scenario = function() {
  addMessage('Hello who are you ?')
  .then(addMessage('Hello I am John'))
  .then(addMessage('Nice too meet you'))
  .then(addMessage('Me too'))
  .then(addMessage('Good Bye'))
  .then(addMessage('Bye'))
} 

scenario()

But with this code all console.log() are made at the same time (after 2500ms), i'm new with promises and i really don't master them.

Thank you !

Upvotes: 2

Views: 268

Answers (1)

Jon Koops
Jon Koops

Reputation: 9261

Thomas has summed it up pretty well in his comment:

then() expects a function, but addMessage() returns a Promise. A Promise ain't a function. And, all your Promises are created at the same time, that's why they fire at the same time

You are constructing all the new Promises at the same time so they will immediately execute and the timers will then also simultaneously end at the same time as well. To mitigate this you can wrap addMessage in a function inside of the .then calls.

addMessage('Hello who are you ?')
  .then(function () { addMessage('Hello I am John') })
  .then(function () { addMessage('Nice too meet you') })
  .then(function () { addMessage('Me too') })
  .then(function () { addMessage('Good Bye') })
  .then(function () { addMessage('Bye') })

Alternatively you could also use Function.prototype.bind() to avoid having to write an anonymous function each time.

addMessage('Hello who are you ?')
  .then(addMessage.bind(null, 'Hello I am John'))
  .then(addMessage.bind(null, 'Nice too meet you'))
  .then(addMessage.bind(null, 'Me too'))
  .then(addMessage.bind(null, 'Good Bye'))
  .then(addMessage.bind(null, 'Bye'))

And of course if your environment is running a recent version of JavaScript you could also use arrow functions:

addMessage('Hello who are you ?')
  .then(() => addMessage('Hello I am John'))
  .then(() => addMessage('Nice too meet you'))
  .then(() => addMessage('Me too'))
  .then(() => addMessage('Good Bye'))
  .then(() => addMessage('Bye'))

In the near future you will also be able to use the await keyword which eliminates the need for any .then calls entirely:

await addMessage('Hello who are you ?')
await addMessage('Hello I am John')
await addMessage('Nice too meet you')
await addMessage('Me too')
await addMessage('Good Bye')
await addMessage('Bye')

Upvotes: 5

Related Questions