Because you don't always have to await a function, and it isn't always possible for the runtime or language to decide whether to "await" or not.
/*
The following code may or may not use an await.
Not await-ing would be better user experience.
*/
async function sendEmails(id) { ... }
async function signUp(userData) {
const user = await db.saveUser(userData);
sendEmails(user.id); // <-- Not awaiting send to complete
return "Congrats. Signup complete!"
}
/*
On the other hand this code needs an await:
*/
async function updateGlobalState(obj) { ... }
async function doSomething(data) {
await updateGlobalState(data); //await needed
return global.x;
}
Sometimes it's really useful to kick off an async function as well, do some other work in the meantime that doesn't require that async function to be done, then await the promise from the async method later on when you do need it to be done.
It's guaranteed to return as soon as the thread of execution finishes prior immediately-pending callbacks (since it's basically a synchronous function call with an awaited return value). It's "finished" as soon as it's finished initiating the send, since it doesn't await the result.
(The exact point where this gets resolved, relative to other pending callbacks/resolutions, is a very wonky detail involving constructs not exposed at the language level, which varies from engine to engine in spite of what the standard says: https://jakearchibald.com/2015/tasks-microtasks-queues-and-s...)
Whenever the call resolves, even if the send does encounter errors, this function or its caller aren't going to know about it either way. That's why this kind of promise-abandonment is pretty bad design - I wouldn't be surprised if there's already a draft in the works for some kind of "use strict" option that causes warnings / crashes when synchronous code finishes with Promises unreferenced (or at least something in tooling / profiling to trace 'promise leaks').