Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it possible to pass in a non-function parameter to Promise.then() without causing an error?

I have the following:

new Promise(resolve => setTimeout(resolve, 2000))
    .then(() => console.log("after 2 seconds"));

new Promise(resolve => setTimeout(resolve, 3000))
    .then(console.log("before 3 seconds (instantly)"));

which produces the following output:

> node index.js
before 3 seconds (instantly)
after 2 seconds

Promise.then() expects a onFulfilled function, but I passed in console.log("before 2 seconds (instantly)"), which is not a function. Two-part question:

  • Why does console.log("before 2 seconds (instantly)") get executed right away (or at all)?
  • Why didn't the second Promise raise an exception when I didn't pass in a function?
like image 772
neverendingqs Avatar asked Feb 07 '17 16:02

neverendingqs


People also ask

How do you pass a parameter to a promise?

To pass parameters to a promise function with JavaScript, we can create a function that takes the parameters we want to returns the promise. to create the f function that takes the username and password . In it, we return a promise created by the Promise constructor.

Does promise run without then?

The code inside the Promise constructor runs when the promise is created and it runs synchronously which surprises some people. So even without then() everything still runs.

What does promise all () do?

all() The Promise. all() method takes an iterable of promises as an input, and returns a single Promise that resolves to an array of the results of the input promises. This returned promise will fulfill when all of the input's promises have fulfilled, or if the input iterable contains no promises.


2 Answers

The code

console.log("before 3 seconds (instantly)")

is an expression, specifically a function call expression. Wherever that appears, it means the same thing, including an appearance as an argument to the .then() method of a Promise. As in any other similar language, an expression used in a function call is evaluated before the function call, so

.then(console.log("before 3 seconds (instantly)"))

results in the console.log() function being called first, with the return value then passed to .then(). That's why you see the message in the console immediately.

Passing undefined to .then() is allowed, and since that's what console.log() returns, there's no error raised.

If you want that console.log() to happen when the Promise is fulfilled, you'd wrap it in a function:

.then(function() { console.log("after 3 seconds"); })
like image 100
Pointy Avatar answered Oct 14 '22 21:10

Pointy


Why is it possible to pass in a non-function parameter to Promise.then() without causing an error?

Yes. All non-function arguments should be ignored. See below.

Why does console.log("before 2 seconds (instantly)") get executed right away (or at all)?

Because in JS the arguments to functions calls are evaluated instantly (applicative order).

Why didn't the second Promise raise an exception when I didn't pass in a function?

Because console.log returns undefined and .then() with no arguments is legal (because both handlers are optional). In your example console.log() returns undefined so it is like calling .then() with no arguments.

But even if it was called with some arguments that are not functions, they would still get ignored. For example even in this example the 'ok' would still get to the console.log at the end, which may be surprising:

Promise.resolve('ok')
    .then()
    .then(false)
    .then(null)
    .then(1)
    .then('x')
    .then([1, 2, 3])
    .then({a: 1, b: 2})
    .then(console.log);

See the Promises/A+ specification, section 2.2.1 that describe the arguments to the .then() method:

2.2.1 Both onFulfilled and onRejected are optional arguments:

  • If onFulfilled is not a function, it must be ignored.
  • If onRejected is not a function, it must be ignored.
like image 44
rsp Avatar answered Oct 14 '22 19:10

rsp