Closed trusktr closed 8 years ago
@dvlsg There we go, synced the README example with the one in the examples folder. I couple things to note:
let log = ...
assignment and used console.log directly.The reason for those four changes is to keep it as minimal as possible for the learning reader. Any thoughts on that?
Those changes are all great, good call.
Two final questions -- what's the tilde in ~async
here? I don't recognize that syntax.
And how do you feel about naming the running function and executing it on the following line for readability? Might just be me, but I think I would personally miss the IIFE at first glance. Maybe. (I'm not super picky either way, just a thought).
But yeah, looks great! Thanks! You can squash/rebase if you want, otherwise I'll just merge it in directly.
@dvlsg
what's the tilde in ~async here?
It makes the async function() {}
a function expression, which can be immediately invoked. basically,
~function() {
// ...
}()
is functionally the same as
(function() {
// ...
})()
The tilde operator operates on the value of the expression, which results in nothing since the result isn't saved. If we try
function() {
// ...
}()
we'll get a SyntaxError.
Basically, using the tilde expression is my favorite way of writing an IIFE. There's multiple ways to do it:
!function(){ /* code */ }()
-function(){ /* code */ }()
~function(){ /* code */ }()
+function(){ /* code */ }()
(function(){ /* code */ }())
(function(){ /* code */ })()
I originally found that in this nice article.
We can apply those to async and and generator functions too:
~async function(){ /* code */ }()
~function *(){ /* code */ }()
but apparently only one form works with arrow functions:
!() => { /* code */ }() // SyntaxError
~() => { /* code */ }() // SyntaxError
-() => { /* code */ }() // SyntaxError
+() => { /* code */ }() // SyntaxError
(() => { /* code */ }()) // SyntaxError
(() => { /* code */ })() // works!
how do you feel about naming the running function and executing it on the following line for readability
I'm okay with that. Maybe the IIFE is more noticeable after having seen that article? x] But yeah, my original intent was to make the example as low level as possible for the learning developer, so perhaps running the function after the definition instead of using an IIFE would suit that goal.
The reason I chose an IIFE was because it was more similar to js-csp's go()
that immediately invokes the wrapped function.
There we go, updated with no IIFE.
Aaaaaaaand squashed!
For fun, I found some other ways to make an IIFE:
typeof function() {}()
delete function() {}()
void function() {}()
new function() {}()
0*function() {}()
0,function() {}()
0>>>function() {}()
iife>function() {}()
iife|function() {}()
That last one is interesting.
iife|async function() {
// ..
await something()
// ...
}()
but works only if iife
is defined. Ah, but this will always work:
'iife'|async function() {
// ..
await something()
// ...
}()
Haha oh javascript. That's clever. I actually use few async IIFEs internally, but I opted for the (async () => { /*... */ })();
syntax.
I'm curious to see if the do
expressions are going to be moved up past stage 0 any time soon. I know they technically work in babel already.
Either way, looks good! Thanks for the contribution, I appreciate it.
@dvlsg Ah, so do { ... }
is basically like an IIFE (I'm guessing with it's own scope)? That's interesting!
The only IIFE I have in my current project is only the entry point.
@dvlsg I thought I'd add to the previous discusson on IIFEs. I re-stumbled on this, which shows why the tilde prefix on the IIFE is better than other options: http://www.joezimjs.com/javascript/great-mystery-of-the-tilde/#comment-654736283
I thought that the ping/pong example better shows the power of CSP, plus it's familiar with people coming from other languages. I also used a custom
sleep
function to show the power of async/await in general, for people who are just starting to discover these concepts.