4 ms·
> Why can't non-async functions use await()? To await means to wait for a Promise to resolve asynchronously. That's why async functions return a Promise instan
by lioeters 5y ago
> Why can't non-async functions use await()?
To await means to wait for a Promise to resolve asynchronously. That's why async functions return a Promise instance.
async function asyncFn() {
const result = await fetch(url)
const json = await result.json()
return json
}
asyncFn().then(json => console.log('Got', json))
console.log('Fetching result..')
Calling asyncFn() will immediately return a Promise instance. Then each await in the function waits for a Promise to resolve, before continuing to the next instruction. While that's happening, other code can keep running, like the last line in the example above.
In contrast, a non-async function is synchronous, which means it's expected to run all instructions one after the other, then return a value. No other code can run while that's happening.
If await was allowed in a non-async function, it would have to block execution of all other code until the Promise is resolved/rejected.
function syncFn() {
const result = await fetch(url) // Stop the world
const json = await result.json() // Stop the world
return json
}
console.log('Fetching result..')
console.log('Got', syncFn())
This is how a synchronous HTTP request works: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Synchronous_and_Asynchronous_Requests#synchronous_request https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequ...
To avoid stopping the world, a non-async function can use Promise callbacks instead.
function promiseFn() {
return fetch(url)
.then(result => result.json())
}
promiseFn().then(json => console.log('Got', json))
console.log('Fetching result..')
- cuteboy19 5y agoYes, but if I am ok with stopping the world, why doesn't JS allow me to do so? Why do we need to have an entirely seperate api for sync http calls when allowing awaiting inside sync functions would have done the same thing?
- Blahah 5y agoJS does - just wrap all your code in an async function, and then you can await within. > async function run() { // call your program logic here await myCode() } > run()
- cuteboy19 5y agoBut this approach would async-pollute all the sync calling functions right? if I had a call tree like function A(){ B()} function B(){ C()} ... function Y(){ await? Z()} async function Z(){...} Then A-Y would need to become async. If await Z() was allowed then we could avoid this. So is there a reason why it could not be implemented this way?
- jdlshore 5y agoBecause JS is single-threaded¹ and is designed for use on the web. If you block that thread, then all event processing ceases—button clicks don't register, scroll events don't fire, etc. So all JS API's are designed to be non-blocking. ¹Not really, but close enough. Originally, this was resolved via callbacks: doSomething((err, result) => { if (err) { ...failure code... } ...success code... } But that got very clunky, resulting in something called "callback hell" and the "callback pyramid of doom." So promises were introduced: doSomething().then((result) => { ...success code... }).catch((err) => { ...failure code... }); But that's also clunky, so the async/await syntax was introduced: try { let result = await doSomething(); ...success code... } catch (err) { ...failure code... } And that's actually quite pleasant to use.
- deleted 5y ago[deleted]
- lioeters 5y agoI haven't tried it and surely not recommended, but I think it's possible to block execution with a while loop until the promise is resolved/rejected. This will be like a "synchronous await", which defeats the purpose of having async functions. function syncFn() { let result let state = 'pending' asyncFn() .then(data => { result = data state = 'fulfilled' }) .catch(error => { result = error state = 'rejected' }) while(state==='pending') {} // Stop the world return result } console.log('Result', syncFn())
- maple3142 5y agoI don't think this will work in JavaScript because that while loop will block the event loop and prevents callback from executing. For example, the following code will be blocked when running in Node.js: function delayedValue(val, ms) { return new Promise(resolve => setTimeout(() => resolve(val), ms)) } function syncFn() { let result let state = 'pending' delayedValue(1234, 500) .then(data => { result = data state = 'fulfilled' }) .catch(error => { result = error state = 'rejected' }) while (state == 'pending') {} return result } console.log('before') console.log(syncFn()) console.log('after')