6 ms·
Neat idea, but what's the point of async-await when you just put await before 100% of calls like in the first example? Now you've got more to type for no gain.
by alpaca128 6y ago
Neat idea, but what's the point of async-await when you just put await before 100% of calls like in the first example? Now you've got more to type for no gain.
I don't get this popularity of async-await, especially in JS where I find its combination of syntax and absence of pre-run checks overly confusing and error-prone.
And this, seriously?
await $`exit 1`
- jiofih 6y agoIf you want to have the same code structure as this, but without await, you’re gonna implement your own queuing system (every call adds an operation to a queue). Many old tools operated this way, before ES6. The problem with that it doesn’t meld together with most third party libs, since they will have no knowledge of your queue and will just execute immediately or out of order.
- devit 6y agoYeah, feels like they should use the Haskell IO monad "do" notation style where the await is implicit unless you use let. This would require the scripts to no longer be vanilla JavaScript, but it seems easy to extend sucrase/babel to do that transpiling.
- efortis 6y agoIn plain JS: pipe(a, b, c) is equivalent to a().then(b).then(c) function pipe(...functions) { (async () => { let accum; for (const fn of functions) accum = await fn(accum); }()); }
- eyelidlessness 6y agoAll IO in JS is async, you either have a Promise-based API (which can be sugared with await) or callbacks. The only exceptions are Node APIs which are explicitly synchronous in their names and CommonJS require. All of which are either discouraged or being generationally phased out (CJS->ESM). That it extends to the $ function (anything preceding a backtick in JS is a “tagged literal” but also a function call) is just API consistency because it can’t know whether you’re calling exit versus something which actually performs IO. So it always returns a Promise.
- megous 6y ago> All IO in JS is async, you either have a Promise-based API (which can be sugared with await) or callbacks. No it's not. There are all kind of *Sync functions even in nodejs and in browsers (there was sync variant of XHR), and JS engine generally doesn't care if you block in your functions or not. JS engines don't even have an event loop, that's just a construct within the app that uses the engine, like nodejs or whatever.
- shepherdjerred 6y agoIn this case it's probably fine to block, but in most others it's absolutely not.
- Raed667 6y agoI'll give you 2 examples and tell me which is more readable: console.log('start') doA() .then(() => { doB() .then(() => { doC() .then(() => { console.log('finish') }) }) }) .catch((error) => { console.log(error) }) Or console.log('start') try { await doA() await doB() await doC() console.log('finish') } catch (error) { console.log(error) }
- leipert 6y agoNo need to nest promises: console.log('start') doA() .then(() => doB()) .then(() => doC()) .then(() => console.log('finish')) .catch((error) => { console.log(error) })
- Raed667 6y agoi was being a bit facetious. "Real-life" code is usually more complex and nesting is needed when you have conditional logic (call doC or doD depending on the return value of the previous call etc..)
- BeefWellington 6y agoIs this not less typing and as clear? console.log('start') doA() .then(doB) .then(doC) .then(() => console.log('finish')) .catch((error) => { console.log(error) })
- mdaniel 6y agoIt's been my experience that doing it that way can fiddle with the `this` value of those B and C functions, although I do in general agree there's usually no need for the outer wrapping arrow function if the interior one doesn't care about `this` I believe your .catch can similarly be `.catch(console.log)` for the same reason
- trog 6y agoHere's a lazy third option: console.log('start') try { doA() doB() doC() console.log('finish') } catch (error) { console.log(error) } It seems to me async/await is a desperate attempt to try to make JavaScript less painful to deal with because of its asynchronous execution nature. I am not a JS expert and have not had many opportunities to work with it extensively, but I confess I have always struggled with this when dealing with JS; I have often wondered if the (alleged?) performance gains from executing JavaScript like this outweighs [what I have always perceived as] the significant extra verbosity and complexity required to manage simply executing things in order.
- hutrdvnj 6y agoIt depends on how sequential your script is. It's not very uncommon to start a background task, do something in the meantime and continue when the bg task has finished. These types of async control flows are very easy to model in JS. And as far as I can see you don't have to await every single statement, because you can do multiple statements await $`echo 1; mkdir test; exit 0`
- CGamesPlay 6y agoI'm really unclear on what repository you're commenting on. The first example shows an example of executing commands in parallel, and does 3 jobs with 1 await. await Promise.all([ $`sleep 1; echo 1`, $`sleep 2; echo 2`, $`sleep 3; echo 3`, ]) The only `exit 1` in the README is an example on how to handle cases where your job fails, so don't really understand what your complaint is.
- alpaca128 6y agoOkay, but why would I do that instead of just sleep 1 && echo 1 & sleep 2 && echo 2 & sleep 3 && echo 3 & wait and be done with it? Now I don't need to prepend 'await $`...`' in front of every other command.
- jiofih 6y agothat’s just ignoring all the other benefits, or pitfalls of bash that you have to worry about. This project is not about enabling better parallelism. (I’ve written massive bash scripts, and now strongly prefer Ruby / python / whatever is available in the system)
- blablabla123 6y agoAlso I think you need to add a trap to make sure the processes exit on ^C.
- alpaca128 6y agoI agree that for complex scripts bash isn't ideal. But my criticism was about unnecessarily verbose syntax. Bash is synchronous by default, this project is the exact opposite.
- mirekrusin 6y agoIf process in the middle exists with non zero exit code, your whole script won't exit with non zero exit code. You have to collect exit codes and check them.
- intergalplan 6y agoIMO it was always a fundamental mistake to force the programmer to deal with the event loop by default. Run async in the background, but present as sync to the developer unless otherwise requested, would have been a much saner design. Unless you're developing a framework or library, odds are good your ratio of leveraging async versus contorting yourself to make it (from your script's perspective) go away will be 1:10 at best. JS keeps coming up with new ways to make this less painful, but it's ridiculous every time because it's a fundamental problem with how Node presents itself. A comical sea of "await"s in front of damn near every call is the modern version of this, and is utterly typical in real JS codebases, but before it's been callback hell, or screwing around with promises all over your codebase when 90+% of the time you just wanted things to execute in order (from your perspective), and so on.
- alpaca128 6y agoI think it's also made much worse by how JS doesn't care about whole classes of bugs. Forgot an `await` somewhere or called an async function assuming it's sync? Now you've got a bug and in some cases no idea where to look for it. TypeScript is also blind to it (although now that I think of it a linter might flag it?).
- intergalplan 6y agoA really good point, and all the more reason to make developer-visible async behavior something the developer has to to ask for, even if the call is in fact async under the hood and might let, say, code handling another request run while it's waiting on I/O. I think a pattern where there are one or two great places at the lowest level of a Node program for program flow to act async, and then a bunch of business logic where it rarely is (probably running "under" the part where async makes sense, if you take my meaning) is far more common than those where async-friendly flow is what you want for over 50% of calls. "Call this chunk of code async, but run everything in it exactly in order" is super-common, and the interface to achieve that is exactly backwards in Node.
- deckard1 6y agoI can't even count the number of times I've seen a unit test giving a false positive (or, perhaps more accurately, not even run) because the developer forgot to properly use async/await or use the done callback.
- tusharsadhwani 6y agoYeah, I saw this yesterday and didn't like it so I made my own cleaner version: https://github.com/tusharsadhwani/zxpy https://github.com/tusharsadhwani/zxpy