2

Perhaps i'm not googleing correctly. does a then function without a paramater not block? for instance, you have a promise:

someFunc = () => {
  return new Promise((res,rej)=>{
   somethingAsync(input).then((val) => res(val))
  })
}

in the following implements of our function. would both wait for the someFunc return val?

someFunc().then(dosomethingafter())
someFunc().then((val) => dosomethingafter())
Jeremy Nelson
  • 276
  • 8
  • 16
  • 1
    your `someFunc` uses the [Promise constructor antipattern](https://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it). It should just be `someFunc = () => somethingAsync(input)` – Patrick Roberts Oct 11 '18 at 22:30
  • `foo(bar())` will always execute `bar` first and pass the return value to `foo`. It doesn't matter what these functions are doing. Arguments are always evaluated before the function is called. – Felix Kling Oct 11 '18 at 22:38

3 Answers3

8

In JS expressions are eagerly evaluated. It means every function argument is evaluated before it's passed.

someFunc().then(dosomethingafter())

is effectively identical to

var tmp = dosomethingafter();
someFunc().then(tmp)

so a function someFunc().then(dosomethingafter()) is invoked before then is called, and its returned result is passed as a parameter.

What you probably meant instead is

someFunc().then(dosomethingafter)

note there is no function call - only a reference to a function is passed to then and it would then be called when a promise is resolved.

zerkms
  • 249,484
  • 69
  • 436
  • 539
3

It is easier to illustrate this via examples. Your first case:

const fn = (text) => {console.log(text)}

const waiter = () => new Promise((resolve, reject) => {
  return setTimeout(() => {
    fn('resolved')
    resolve()
  }, 2000)
})

waiter().then(fn('done'))

Notice that fn got executed first, got evaluated and then the waiter got executed.

Lets look at the 2nd case:

const fn = (text) => {console.log(text)}

const waiter = () => new Promise((resolve, reject) => {
  return setTimeout(() => {
    fn('resolved')
    resolve()
  }, 2000)
})

waiter().then(() => fn('done'))

Notice now that we got resolved first and then done.

So the answer to your question is yes in both cases we will wait and execute the someFunc or in the above example the waiter.

The main difference really is when does your dosomethingafter get executed.

In the first case it is right away and then it is passed in the waiter.

In the second case you have a valid promise chain which will first be executed and then once done (and since fn acts as the function handler of the then) it will execute dosomethingafter.

Akrion
  • 18,117
  • 1
  • 34
  • 54
1

pass doSomethingafter first class

const handleAsJson = response => response.json()
fetch(url)
  .then(handleAsJson)
  .then(console.log)
Benny Powers
  • 5,398
  • 4
  • 32
  • 55