-1

On Medium, I red an interesting article that explains a certain problem. However, this article does not provide a sufficient solution.

Copied form https://medium.com/javascript-in-plain-english/you-dont-know-javascript-until-you-can-beat-this-game-aa7fd58befb


const asyncOperation = fetch('something.com');
asyncOperation.then((resolvedValue) => console.log("Horse A"));
console.log("Horse B")

Results

Horse B
Horse A

Explanation

This is one that people consistently get wrong. It’s a common misconception that calling .then on a Promise will cause JavaScript to immediately invoke the function inside of the .then function.

After all, you clearly have access to resolvedValue before calling console.log("Horse B") , or at least that’s the order in our script. It’s even named such that once you have your Promise object, you can THEN see what’s inside of it. But this is misleading. The .then method should really be renamed to .wheneverThisValueGetsResolved (unfortunately, not as sexy).

Here is what JavaScript is really doing: when we call fetch , we get back a Promise object. This Promise object actually has two hidden properties, value and onFulfilled. When we push fetch on to the call stack, it gets sent off to the browser APIs and does its work in the background, similar to the setTimeout method. While it’s doing this work, all subsequent synchronous operations are performed, like before. But wait, we explicitly called .then on our Promise before moving onto console.log! Well…this is where the two hidden properties value and onFulfilled come into play.

When our background operation is finished, it updates the value property of our Promise. When this happens, this value is automatically passed into the onFulfilled property. Okay, but what’s so special about onFulfilled ? The answer is that the function that you passed into the .then method actually gets pushed onto the onFulfilled property of the Promise. In other words, console.log("Horse A") is actually pushed on to the onFulfilled property of our Promise. When the Promise finally resolves, (i.e., we get back our value), THEN the function(s) in onFulfilled gets to be executed. This is why .then should really be named .wheneverThisValueGetsResolved.

TL;DR: the function that you write inside of the .then method only gets executed when the Promise itself is resolved. Not immediately upon calling .then on the Promise.


My Question How do I make JavaScript to immediatly invoke the function inside of the .then function ? I often have to deal with this kind of problem that JS behaves async when i do not need it.

What should happen in the above mentioned code to create the following result:

Horse A 
Horse B
Jimbo.Koen
  • 151
  • 10
  • 1
    "My Question How do I make JavaScript to immediatly invoke the function inside of the .then function" — You can't. That's **why** `then` exists in the first place. – Quentin Jun 15 '20 at 19:17
  • You can't, pretty much by definition. Promises are asynchronous, they're *designed* so that you can never get "horse A" printed first here. – Robin Zigmond Jun 15 '20 at 19:18
  • You can use an IIFE if you truly want to run something synchronously, but in the majority of cases, you shouldn't have to https://jsfiddle.net/jcLngbxe/ – Alberto Rivera Jun 15 '20 at 19:20

3 Answers3

2

Using promises or async/await you can make can control the execution flow.
For more info. you can follow these articles:
Promises - https://javascript.info/promise-basics
Async/Await - https://javascript.info/async-await

Possible Solution:

async function test() {
    const asyncOperation = await fetch('something.com');
    const response = await asyncOperation.json();
    console.log("Horse A");
    console.log("Horse B");
}
test();

Output:

Horse A
Horse B
Shivanshu Gupta
  • 324
  • 2
  • 9
  • That's a totally different situation you've illustrated, which has essentially no similarity with the code in the OP. – Robin Zigmond Jun 15 '20 at 19:17
  • That's just like putting both the console log statements in the `then`. It doesn't cause the `then` to be invoked immediately. The `test` function goes to sleep until the data is ready. – Quentin Jun 15 '20 at 19:19
1

To get the result you want you'll have to make the console.log statement execute in async. One way ( kind of hacky ) is to wrap it in setTimeout with a 0ms delay so that it gets deferred to the task queue.

const asyncOperation = Promise.resolve()
asyncOperation.then((resolvedValue) => console.log("Horse A"));

setTimeout(()=>console.log("Horse B"), 0)

You can't immediately execute the handler inside then. It's not what it is intended for.

For a better understanding I would suggest you to watch this : https://www.youtube.com/watch?v=8aGhZQkoFbQ

Hope this helps !

Hemant Parashar
  • 3,684
  • 2
  • 16
  • 23
0

If your question is "how to get the .then callback to execute instantaneously", the answer is you can't. .then callback gets called only when the underlying promise is resolved. This is up to the logic in the promise, not how you call .then.

If your question is "how can I make this logic behave synchronously", the answer would be to look at async/await.

jmkmay
  • 1,441
  • 11
  • 21