Tuesday, 27 December 2016

javascript - How can I use async/await at the top level?


I can't seem to wrap my head around why this does not work.



Because main returns a promise; all async functions do.


At the top level, you must either:



  1. Use a top-level async function that never rejects (unless you want "unhandled rejection" errors), or


  2. Use then and catch, or


  3. (Coming soon!) Use top-level await, a proposal that has reached Stage 3 in the process that allows top-level use of await in a module.



#1 - Top-level async function that never rejects


(async () => {
try {
var text = await main();
console.log(text);
} catch (e) {
// Deal with the fact the chain failed
}
})();

Notice the catch; you must handle promise rejections / async exceptions, since nothing else is going to; you have no caller to pass them on to. If you prefer, you could do that on the result of calling it via the catch function (rather than try/catch syntax):


(async () => {
var text = await main();
console.log(text);
})().catch(e => {
// Deal with the fact the chain failed
});

...which is a bit more concise (I like it for that reason).


Or, of course, don't handle errors and just allow the "unhandled rejection" error.


#2 - then and catch


main()
.then(text => {
console.log(text);
})
.catch(err => {
// Deal with the fact the chain failed
});

The catch handler will be called if errors occur in the chain or in your then handler. (Be sure your catch handler doesn't throw errors, as nothing is registered to handle them.)


Or both arguments to then:


main().then(
text => {
console.log(text);
},
err => {
// Deal with the fact the chain failed
}
);

Again notice we're registering a rejection handler. But in this form, be sure that neither of your then callbacks doesn't throw any errors, nothing is registered to handle them.


#3 top-level await in a module


You can't use await at the top level of a non-module script, but the top-level await proposal (Stage 3) allows you to use it at the top level of a module. It's similar to using a top-level async function wrapper (#1 above) in that you don't want your top-level code to reject (throw an error) because that will result in an unhandled rejection error. So unless you want to have that unhandled rejection when things go wrong, as with #1, you'd want to wrap your code in an error handler:


// In a module, once the top-level `await` proposal lands
try {
var text = await main();
console.log(text);
} catch (e) {
// Deal with the fact the chain failed
}

No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...