If we wanted this to work while we are waiting on TC39/TypeScript, we would have to do a bit of _hackery_.
When emitting a module with TLA, we would have to specifically ignore the diagnostic error related to that. TypeScript always emits, it is _us_ who then chooses to throw. I _might_ be a good idea to actually log a warning, since when TLA arrives, it could be a different behaviour to what we would have.
Then we would have to modify the AMD factory function to be async
and deal with awaiting the promise resolution returned from that factory before we consider the module "resolved".
The drawback, like the module specifiers ending in .ts
, we won't be able to get any of the editors to accept this code... so while it will run properly under deno, it won't look pretty in editors.
https://github.com/tc39/proposal-top-level-await#optional-constraint-top-level-await-can-only-be-used-in-modules-without-exports
Potentially it will be easier to do with this restriction. We only really need it for "main" scripts.
TC39 start promoting it.
Do we want to be part of it?
https://github.com/tc39/proposal-top-level-await/issues/42
Well, one member of TC39 is trying to get it moving again. I am not sure we can really add anything to it. The biggest challenge is that they need to address the functional challenge that top-level await and how modules are evaluated and as Ry mentioned above, the optional restriction would make it a lot easier, but this is really needs the implementors to figure out how to do it, versus adding another voice to the mix.
Top level await has gone Stage 3. That means that the TypeScript team should be willing to implement it now.
A V8 issue has been created for this https://bugs.chromium.org/p/v8/issues/detail?id=9344
The TypeScript team are indicating that it will be challenging to downemit and are considering not allowing a downemit. That is find from our perspective, but that "problem" continues to delay them addressing the issue.
https://chromium.googlesource.com/v8/v8.git/+/591d1c9de4b3f2e4159c01d57f2c1e6e37d7cb41
TLA support has landed in V8
TLA is scheduled for TS 3.7 as well (early-November): microsoft/TypeScript#33352
Parsing support has landed https://chromium.googlesource.com/v8/v8.git/+/0ceee9ad28c21bc4971fb237cf87eb742fc787b8
Deno v0.19 has integrated the changes from V8 and has a test demonstrating TLA.
However this is JS only support. We still need TS to not barf on TLA syntax. Therefore I'm leaving this issue open until we have a corresponding tests/top_level_await.ts
.
That should be doable without ignoring error codes with TS 3.7 on Nov 5th.
@kitsonk In this latest TS 3.7 announcement, there is no indication that there will be any support for TLA by Nov 5th.
That is the beta, and the announcement is what is in the beta. The iteration plan mentioned above still lists it. I am sure Ry and I will chat to the team about it next week at TSConf.
In case people are following this, here's v8 issues for top-level for-await (not merged yet):
https://bugs.chromium.org/p/v8/issues/detail?id=9817
https://bugs.chromium.org/p/v8/issues/detail?id=9825
Also, I had a chat with Daniel R, PM on TypeScript team, and TLA won't make TypeScript 3.7. It simply causes us to ignore the error message in Deno and will show it as invalid in editors, though it will run fine under Deno.
In this latest TS 3.7 announcement, there is no indication that there will be any support for TLA by Nov 5th.
guess I was right then..
did Daniel R give a reason why it won't be included?
Yes, not enough time in the team. I think some of the other features took longer than they anticipated.
Actually, re-reading those commits above I think top-level for-await is in recent V8 versions. IIRC this means we can support it in ts easily once we upgrade V8.
I see that TypeScript now has first release with Top Level Await at 3.8. Does this help the progress of TLA in Deno?
Deno has TLA. You are commenting on a closed issue.
Thanks.
Deno has TLA. You are commenting on a closed issue.
This example seems to not work :
function add(a: any,b: any,c: any): any{
if(a+b>10){
return c("My error",a+b);
}else{
return c(null, a+b);
}
}
try{
let t = await (async()=>{
return add(4,5,(e: any, r: any)=>{
if(e) throw e;
return r;
});
})();
console.log(t);
}catch(e){
console.log("Yes! caught error from call back: ", e);
}
Gives me this error:
error TS2304: Cannot find name 'await'.
@anuragvohraec this is a TypeScript problem, and the error is a mis-leading... because you don't have any imports or exports in the module, TypeScript is treating this like a script instead of a module. This is causing the parsing in the try block to be a bit off, and instead of telling you that the module isn't a module error, it is giving you this strange error.
To work around the issue just add the following at the start or the end of the module:
export {};
To work around the issue just add the following at the start or the end of the module:
export {};
still same error :
export {};
function add(a: any,b: any,c: any): any{
if(a+b>10){
return c("My error",a+b);
}else{
return c(null, a+b);
}
}
try{
let t = await (async()=>{
return add(4,5,(e: any, r: any)=>{
if(e) throw e;
return r;
});
})();
console.log(t);
}catch(e){
console.log("Yes! caught error from call back: ", e);
}
@anuragvohraec - Pardon my N00b question, but when would you use the (async(){...})()
in real world logic in Deno?
From my understanding, all functions in Deno
are implicitly async and I'm not sure if this makes this async()...
methodology redundant?
No, not all functions in are implicitly async
. Only the global scope (so the top level of a module outside of a function scope) and all function scopes declared with the async
keyword.
await foo() // valid here
function test1() {
await foo() // invalid here
}
async function test2() {
await foo() // valid here
}
More info on top level await: https://v8.dev/features/top-level-await
@lucacasonato - Thanks, that makes sense.
I found a good example explaining the use of async()=>
here.
@anuragvohraec - Here is a tweak to your code that works for me:
function add(a: any,b: any,c: any): any{
if(a+b>10){
return c("My error",a+b);
}else{
return c(null, a+b);
}
}
(async()=>{
try{
let t = await (async()=>{
return add(4,5,(e: any, r: any)=>{
if(e) throw e;
return r;
});
})();
console.log(t);
}catch(e){
console.log("Yes! caught error from call back: ", e);
}
})()
@anuragvohraec it is a TypeScript lexing issue. Upstream bug filed: https://github.com/microsoft/TypeScript/issues/38483.
@anuragvohraec - Pardon my N00b question, but when would you use the
(async(){...})()
in real world logic in Deno?
The real world example for this will be to convert a call back based asynchronous function be converted to async await based without using a Promise API.
If you see my example:
function add(a: any,b: any,c: any): any{
if(a+b>10){
return c("My error",a+b);
}else{
return c(null, a+b);
}
}
try{
let t = await (async()=>{
return add(4,5,(e: any, r: any)=>{
if(e) throw e;
return r;
});
})();
console.log(t);
}catch(e){
console.log("Yes! caught error from call back: ", e);
}
c
is a callback function.
I was trying to use a IIFE to convert my call back back based asychronous function to an async-await based function (without using an explicit Promise API).
No, not all functions in are implicitly
async
. Only the global scope (so the top level of a module outside of a function scope) and all function scopes declared with theasync
keyword.await foo() // valid here function test1() { await foo() // invalid here } async function test2() { await foo() // valid here }
The code I have shared do not commits any mistake mentioned in your code samples.
The code I have shared do not commits any mistake mentioned in your code samples.
@anuragvohraec I don't think @lucacasonato was complaining about your code, but was just trying to inform @JavaScriptDude on how async/await works. Your code is valid JavaScript, and should be valid TypeScript but TypeScript has a bug.
is TLA supported in deno REPL?
I cant seem to get the following to work.
using Deno v.1.0.0
$ deno
> console.log(await Promise.resolve('Success'))
It just seems to await indefinitely without outputting anything or allowing me to input any further commands.
@somombo I believe #3700 is tracking the addition of top-level await to the REPL. For me (1.2.0 and 1.3.0) using top-level await in the REPL throws an error:
Uncaught SyntaxError: await is only valid in async function
at evaluate (rt/40_repl.js:60:36)
at replLoop (rt/40_repl.js:160:15)
Most helpful comment
Top level await has gone Stage 3. That means that the TypeScript team should be willing to implement it now.