5

I've been trying to learn the JS concurrency model given a background in Python's.

Running the following in Python:

async def myFunction():
    print("abc")

myFunction()

will print nothing. Running the following in JavaScript:

async function myFunction() {
    console.log("abc")
}

myFunction()

will print "abc". In both cases I did not await myFunction, yet the evaluations were different.

I understand why the Python program prints nothing. myFunction is a coroutine function that resolves to nothing, more specifically it returns an Awaitable[None]. But to actually have this awaitable's side effect executed, I must await it.

I have also read Are promises lazily evaluated? with an answer of no, talking about how the eager evaluation of promises is guaranteed.

Even though I've looked at both concurrency models separately, their difference is still confusing. While general clarity about the contrast here would be very helpful, I also do have a specific question: Is there ever a point to awaiting a Promise in JavaScript that resolves to nothing, and should only execute for its side effect? In other words, do await myFunction() and myFunction() possibly have a difference in behavior in a different case, even though they both gave the same output here?

Mario Ishac
  • 5,060
  • 3
  • 21
  • 52
  • I don't know much about the Python way... For the JS way: `await myFunction()` and `myFunction()` will always evaluate `myFunction()` in the same way. The only difference is for the caller, that only in one case waits for the promise to resolve. You could [learn about the event loop here](https://javascript.info/event-loop) (when are promises executed, for example) – Josef Wittmann Jan 06 '21 at 06:53

2 Answers2

5
async def myFunction():
    print("abc")

awaitable = myFunction()

In Python, myFunction() returns an awaitable. The code hasn't run yet. It only runs when you execute a method (.send()) on the awaitable:

awaitable.send(None)

You typically don't use .send(), these mechanics are hidden. You will just use await myFunction() or asyncio.get_event_loop().run_until_complete(myFunction()), and this will execute the function's code behind the scenes.

In JavaScript, an async function returns a promise. The MDN JS reference says:

Promises in JavaScript represent processes that are already happening

So when you call the async function in JavaScript, the function's code starts running, and at some point a promise is returned. Here's what the MDN JS reference says about it:

The body of an async function can be thought of as being split by zero or more await expressions. Top-level code, up to and including the first await expression (if there is one), is run synchronously. In this way, an async function without an await expression will run synchronously. If there is an await expression inside the function body, however, the async function will always complete asynchronously.

Given all this, I don't see why you would await an async JS function if you only wanted its side effect (unless the caller needs the side effect to have occurred before proceeding).

Antonis Christofides
  • 6,990
  • 2
  • 39
  • 57
1

Inside an async function all the asynchronous operations are done by using an await in front of it.

If there is an await in front of a promise, then the we wait until the async operation is completed and then continue the remaining code execution.

If we don't use await infront of an async operation, we don't resolve the promise and continue.

Await in front of a synchronous operation has no effect.

// Case I

const test = async() => {
     let res = fetch("http://localhost:3000");
     console.log(res);
     console.log("It is working");
     // We dont wait for the http request to complete,
     // We print res as a <<promise>> 
     // and continue to the next line and print "It is working".
}

 test();

// Case II

const test = async() => {
   let res = await fetch("http://localhost:3000");
   console.log(res);
   console.log("It is working");
  // We wait for the http request completion. 
  // After that we print the result.
  // Then print ===> It is working
}

test();


  ()=> {} // stands for an anonymous function also know as Fat arrow function.

You use await in front of a function only if it returns a promise. If it returns a promise, we wait for the promise to resolve and continue code execution. If it doesn't returns a promise, default behavior is expected.

    const test = () => {

    return fetch("http://localhost:3000");

    }

    let testingAsynFunc = async() => {
        let a = await test();
        //Here we wait until the promise is resolved and then continue the code execution.
        console.log(a);
        console.log("working");
}

testingAsyncFunc()
Hrushikesh Rao
  • 109
  • 1
  • 4