Is async / await useless?

  Рет қаралды 58,233

Fun Fun Function

Fun Fun Function

Күн бұрын

Пікірлер: 358
@funfunfunction
@funfunfunction 6 жыл бұрын
💖 This episode is sponsored by Tiptapp, they are currently hiring. Work with React Native or node.js in the heart of Stockholm. tiptapp.com/fff
@andrerothweiler9191
@andrerothweiler9191 6 жыл бұрын
Work in a country with a tax rate up to 60% and over 50 no go areas? No, thank you!
@cryptochannels7433
@cryptochannels7433 6 жыл бұрын
Conciseness, readability & maintainability > Cleverness.
@DavidWMiller
@DavidWMiller 6 жыл бұрын
Certainly, what was referred to as "clever" in this video I have very different words for ;)
@Seedzification
@Seedzification 6 жыл бұрын
yes his one liner mess, I wouldn't call that clever at all
@zeeeeeman
@zeeeeeman 6 жыл бұрын
Agreed. A one liner in ternaries is impenetrable to console.log. Good for code golf, not for real world.
@JohnWick-rc9qq
@JohnWick-rc9qq 6 жыл бұрын
Functional programming relies heavily on ternaries and recursion as it favors expressions over statements. They're very useful for the real world. It just takes a little getting used to if you've used `if` and `for` your entire life. It' just like learning any language feature -- you're not comfy until you know it.
@electroaddiction
@electroaddiction 5 жыл бұрын
@@JohnWick-rc9qqIf every developer takes a little to get used to, I wonder the amount of time wasted in the end.
@AngusMcIntyre
@AngusMcIntyre 6 жыл бұрын
Replacing loops with recursion is exactly the sort of behaviour that async/await is trying to avoid - the transpiler emits this code so that you don't have to. Recursion is harder to reason about and you can introduce all sorts of fun performance issues. For example - how many arrays have you created there? Long story short - you rewrote the async/await code with more characters, more calls and more conditions. Would you write for-loops with goto? 😉
@victorb9503
@victorb9503 6 жыл бұрын
Where I'm working on right now (and in most previous gigs actually) we are used among other things to write API tests which by nature are async: do this to the db, make a http request, check how the db changed after that request was completed successfully, etc. And we used to do that with either Promises or the "async" js library. When async await got into the lts version of node.js I took one of the test files and converted it, then looked at the diff. Not only was far fewer lines (I think it was a 2x reduction in total lines) but the identitation was kept to a minimum and the lines were easier to follow and read out loud.
@hamaralsilva
@hamaralsilva 6 жыл бұрын
This video can be renamed to "how to get things worse by using promises instead of async/await". 😂
@rudde7251
@rudde7251 6 жыл бұрын
This is proof JavaScript developers have the highest occurrence of hipsters.
@Assassunn
@Assassunn 6 жыл бұрын
But async DOES return a promise, and await waits a promise is resolved while stopping the execution of the following instructions (which wouldn't be possible using then() ! and that's the power of async/await, not a sugar syntax feature)
@gillianbc
@gillianbc 4 жыл бұрын
I can see the advantage of this when you put the generic waitForEach() into a utility module. In your code module, you only then need to define the function you want applying to each of the items. It does make it cleaner and more readable
@ProgramArtist
@ProgramArtist 6 жыл бұрын
I am not against promises and don't have any strong opinions to prefer one over the other but here is what I think about the things you said in the video: The complexity of the code is not measured only by how nested it is, it is also measured by the number of things you need to keep in mind while reading the code itself. 13:32 you said you had to think about the code and after you figured it out it felt simple. For me, a sentence like this means the code smells. I prefer the code to read like a well-written book and not like a smart poem. What I mean by that is that in well-written poems, you need to stop and think about every line and understand the meaning of it and how it contributes to the idea of the poem. In the book, on the other hand, you will read much more but the idea will be much more clear to you and you will get it faster. Also for me, a code with promises looks a lot like a code with streams (like in RX for example), and it sometimes feels like reading a very long sentence with many ideas in it, you get lost in the middle and go back to re-read from start. I prefer reading short sentences one by one and breaking the ideas apart. Probably you can refactor async/await code to promises in a good and understandable way, but it is harder to do so and there are much more ways to get it wrong.
@ErnestGWilsonII
@ErnestGWilsonII 6 жыл бұрын
I see folks juggling to avoid a flat out admision that async/await is better on long complex multi-step asynchronous programs. Mixing Promise and Promise All with a main driver script that uses async-await is a huge improvement to code readability. First learn callbacks, then write everything Promise / Promise All style and then graduate to writing the main body of your program in async/await style, this is really satisfying and super readable allowing anyone following in your footsteps to easily reason about your code, a clear sign that async-await carries less technical debt.
@AjdenTowfeek
@AjdenTowfeek 6 жыл бұрын
First of all, big fan of your show, but you guys really struggled trying to argue that async await is useless in this episode and imho failed miserably ;-) From my experience simplicity and readability is always preferable over complexity especially in larger organizations where the skill may vary quite a lot among the developers. Developers being proud of being clever when performing such basic operations/tasks is usually a red flag. Nobody in their right mind can say that the second (sql) sample is more readable and more straightforward after the refactoring. You guys literally made me laugh when you couldn’t motivate why the refactored code was better other than “I like it because it’s recursion, it’s neat because it’s recursion, it just feels *arghh*”, really? The code became more complex after the refactoring and the argument that it makes you think harder to write that code comes up short imo. You said it yourself, “it’s hard for me to figure it out, but once I have it, it’s simple”. Honestly which code would you prefer to debug and find bugs in? Something you understands immediately and could write up without even thinking or something that feels so great because it’s recursion but you don’t understand it right away?
@funfunfunction
@funfunfunction 6 жыл бұрын
We did not argue that. :)
@danilocecilia7831
@danilocecilia7831 6 жыл бұрын
for me being a 'noob' , as my point of view, the first example is way better understandable and honestly I am still trying to figure it out the recursive refractory solution, feel so stupid right now... =(
@iandashb
@iandashb 6 жыл бұрын
Async/await removes a lot of cognitive load from the Devs trying to work out what the recursive function is doing in the Promise rewrite. The asynchronous/await would be my preference, especially for debugging, but interesting point about error handling....
@JoshuaMuniandy
@JoshuaMuniandy 6 жыл бұрын
I agree. As a noob programmer, I always find Promises daunting. But when I started learning Async Await, I found it easier to code, read & debug. I found that 2nd example of the SQL code was way too complexed esp with the recursion.
@adambechtold6741
@adambechtold6741 6 жыл бұрын
They also missed an obvious opportunity to run their processUser function in parallel. Instead of calling await in the for loop, they could have collected those promises in an array with awaited Promise.all(). In many cases, this would have been faster than both their examples.
@TheMasterpikaReturn
@TheMasterpikaReturn 6 жыл бұрын
Some thoughts as I watch the video. Also, I'm a functional programming enthusiast, and use quite a lot of haskell in my free time, so there will be a lot of Haskell comparisons. 1- Is async await useless? I'm torn on this one. These days I mainly write Haskell in my free time, and async-await feels like an ad-hoc version of do-notation (much like promises feel like an ad-hoc version of a generic monad typeclass). So I wouldn't say it's useless, but the fact that they had to add an ad-hoc syntax for an ad-hoc construct kinda bothers me. 2- I think code with promises would be much clearer if "if" was an expression instead of a statement... 3- Couldn't you get rid of the nesting by just wrapping `server.getMaxNumberOfBurgersPerDay()` in a Promise[.resolve()], so you can call `then` after the outer `then`? (so it becomes server.hasBurgers().then(.....).then(....)). 4- I don't agree with the "in your face" thing: personally I think that asynchronous flow should be as implicit as possible. For example, haskell's I/O is non-blocking, but while coding you don't really think about it. In my opinion, we should be able to program in a style that looks like synchronous code, but can be asynchronous, and it should be the language's job to transform between those representations. It's a lot like callback hell: it's pretty much Continuation Passing Style, and you can do it manually... but why do it when you can have a CPS-like Monad (like haskell's Cont") and write code that doesn't really look like CPS (albeit with the occasional callCC)? 5 - in the for loop example, i'd think you could so something like `users.map(user => await processUser(user.id))`, can't you? 6 - wait for each looks like a fold dying to come out. Maybe some sort of `compose(foldr(then), map(processFn)`? [where then(a,b) = a.then(b) 7- also, array destructuring feels like ad-hoc pattern matching :D although I guess it's not as ad-hoc, cause you can use it with objects too? 8- the stuff about error handling and aggregating data to me feels more of a consequence of the fact that Promises are very functional(as in functional programming) of a construct, and Javascript doesn't have very good support for functional programming, which means that there's quite a bit of stuff that you can't really do without it feeling weird or convoluted. It always feels like JS features are kinda thrown there, and don't really compose very well with each other. But hey, that's just my 2c, feel free to disagree
@dungandonuts
@dungandonuts 6 жыл бұрын
Pika ^_^ you had the same idea as me that the last example could have been a fold/reduce! When I first saw destructuring it did remind me of Haskell's patten matching and here is the same as the x:xs pattern. It's kind of a shame that JS doesn't have a concept of monads because Async/await basically is just do notation but only for promises.
@dimaorols8143
@dimaorols8143 6 жыл бұрын
In my opinion async/await only offer a syntactical sugar on top of promises themselves. - Writing Promise.all(users.map(user => processUser(user.id))).then().catch() is better as it would resolve items in parallel and fail on failure. - Generators can be similar if considering that every generator is pausable and can have it's own state during execution. That can be recreated with a curried function where it's inner function uses closure declarations for internal manipulation. - As for curiosity you could look at LiveScript transpiler. It doesn't use async/await and it's closer to functional programming than CoffeeScript: livescript.net/#
@TheMasterpikaReturn
@TheMasterpikaReturn 6 жыл бұрын
Oh I forgot about Promise#all. That's most likely the best option. Generators... eh I always found them kinda clunky to use. Also I already know of livescript, and it's one of the options that I considered before learning haskell, but nowadays I can use haskell on the front-end too (either ghcjs or purescript, which is very similar), so I never looked into it again.
@artgreg2296
@artgreg2296 6 жыл бұрын
Especially agree with your point 3. "then chaining" was meant to avoid nesting
@justvashu
@justvashu 6 жыл бұрын
Art Greg the thing about then chaining is that it really starts to break down when you depend on the result of a previous promise or many others. Then you need to start nesting and have to get clever with the flow of code in order to pass values along or follow conditions. It also makes the code a little harder to break down into simpler units for testing because all the promises are coupled with the one that provided it’s required data. There are ways around it of course. The thing I like about async-await is that I can unit test the code without promises if it’s more practical.
@BrandonBey
@BrandonBey 6 жыл бұрын
Oh no, is MPJ saying you should write clever code again :( Code styles are mostly a personal preference thing - if you are writing for yourself, go ahead and be clever. If you are wiring code that is to be shared - making it less clever and more clear is always better.
@Sworn973
@Sworn973 6 жыл бұрын
6:37 "it is not to bad". Everything in one big line, lambda, with nested promise with a lambda with inline if, with another promise with another inline if. Definitely is not to bad, is insanely bad. IF the main point of the away is to create better code, Yeh it works, but as everything else in programming if not used with sanity, it will end up with nightmare mess. Even in functional programming breaking down those inline nested mess will make it more clean. 15:05, return a inline calls will never be "clean". As you said, "We return the query, than we process the user" ops, Return, end of function. So it is not so clean and have traps just "await"ing for unaware people. The actual order of the inline call can be trick. Specially if you throw some lambda with recursion. if you write like you tried to say query get users process that is clean, And you return what ever is needed;
@emretekince
@emretekince 6 жыл бұрын
of course it's useful. simple, clear and readable code!
@AndreasWindt
@AndreasWindt 6 жыл бұрын
Exactly! As satisfying as it can be to come up with a solution like the one in the second example, it might become very hard to grasp what it does at first sight (one could say, »it was hard to write, it has to be hard to read«). I'd definitely prefer the async/await form of it for maintainability!
@hajimeyamasakivukelic7235
@hajimeyamasakivukelic7235 6 жыл бұрын
Here's a missed opportunity. Throw exceptions into the mix (pun intentional), and suddenly promise-based code look much better. Also, the example code has bad separation of concerns in general, and promise-based solution tend to push you towards solving those issues as well. Overall, async/await encourages some bad patterns if you look at it carefully.
@vlad981
@vlad981 6 жыл бұрын
TL;DR, no it;s not useless )
@Ozziepeck11
@Ozziepeck11 6 жыл бұрын
Vlad it’s
@u4yk
@u4yk 6 жыл бұрын
So... Betteridge's Law, then...
@LoveLearnShareGrow
@LoveLearnShareGrow 6 жыл бұрын
I absolutely love that I scrolled down to see all the comments were about READABILITY. I'm only a junior programmer, so I can't say what senior programmers will find "easy to read" but recursion (as much fun as it is to write) is *horrible* for readability. And the main thing I hate about promises is that it keeps breaking up the scope so that I have to do weird tricks to pass data from the top to the bottom. Async/await solves those problems, at least when you don't need fine grained try/catch blocks. It's usually very easy to read and very easy to pass data where it needs to go. I love it.
@nachovalera5217
@nachovalera5217 6 жыл бұрын
I like your video because it shows to me async/await is life❤️ even if you don't want to prove that I understand what happens behind async / await and I think it is a great improvement to the lenguage because it helps you solve real tasks faster and helps you think at a higher level I like that type of promises hell for educational purposes but not that much for real life anymore having async/await
@joaofnds
@joaofnds 6 жыл бұрын
10:18 why not: function proccessAllUsers() { const sql = 'SELECT id FROM users' db.query(sql, []) .then(users => Promise.all(users.map(proccessUser))) }
@funfunfunction
@funfunfunction 6 жыл бұрын
Because that would change the meaning of the code example. The example illustrates sequential promise processing.
@GodOfMacro
@GodOfMacro 6 жыл бұрын
and what about db.query(sql, []) .then(users => users.reduce((q, u) => q.then(u => processUser(u.id)), Promise.resolve()))
@funfunfunction
@funfunfunction 6 жыл бұрын
Yep, that works great!
@sney2002
@sney2002 6 жыл бұрын
There is an error in waitForEach which makes it run in parallel instead of sequentially. the next call to waitForEach must be inside of a function call: processFunc(head).then(() => waitForEach(processFunc, tail))
@modernclics
@modernclics 6 жыл бұрын
I totally agree on using Promise.all despite of what the original async / await code was trying to prove. IMHO the proposed solution on the video looks unnecessarily complex. In the end Javascript is asynchronous and the most coherent way to wait for a set of promises is using Promise.all. Maybe Matt and David should have consider a different approach for the video like: "Javascript is asynchronous, don't try to make it look like it isn't" and propose simpler algorithms using promises. Disclaimer: This is not a rant, I'm a big FFF fan. :D Cheers!.
@wmhilton-old
@wmhilton-old 6 жыл бұрын
At 14:00, won't `waitForEach` silently swallow errors generated by processFunc?
@maagiapall
@maagiapall 6 жыл бұрын
One of the big reasons I much prefer the async/await version for getHamburger is this: imagine you're seeing this function for the first time, in the middle of a random codebase, no documentation, maybe the function isn't named as clearly... And you need to figure out exactly what the function returns. In the async/await example, I can scroll right down and see that it returns defaultBurger, or loadBurgers depending on the branching. In the case of promises, I have to sort of start following what's being returned at each level of indentation and slowly work my way to the end to see what's being returned. I could technically skip to the deepest level of indentation, but in that case I might miss some logic that happened before. This might take 2 seconds or 20 seconds longer, but the point is, it's time that you have to take to figure stuff out, as opposed to the async/await version which reads like a book. The more we can avoid these 2-20 second distractions, the less tired we will be 2, or 4, or 8 hours into the work day. And the more productive we will be as a result. So even if the code is only slightly more readable, to me that's a big win.
@RazvanLaurus
@RazvanLaurus 6 жыл бұрын
async / await is certainly an improvement. It doesn't require as much boilerplate as promises do (or callback style) and it makes the code easier to reason about, thus more maintainable. As for the conclusion of this episode, that functional recursion is an alternative, do keep in mind that recursion is not "safe" in JS. Not all platforms support tail call optimization, hence with long lists (high depth), there's always a risk to run out of stack.
@SimonScarfe
@SimonScarfe 6 жыл бұрын
Great video! Is there any light at the end of the Proper Tail Calls / Tail Call Optimisation tunnel in JS-land? At the minute I'd hesitate before reviewing any code using recursion with arrays of unknown size, unless I was developing only for Safari.
@HermanWillems
@HermanWillems 6 жыл бұрын
There is Tail Call Optimisation is a specification of ES6... Not sure about the details though jsperf.com/tco#chart=bar
@bloodaid
@bloodaid 6 жыл бұрын
This reminds me a little bit of the whole "assembly programming is better..." argument people used to have once high level languages started to appear. Async / Await are simplifiers. USE THEM!
@matthewbarbara2916
@matthewbarbara2916 6 жыл бұрын
You said something like this one on the burger code "This code is horrible and it has a very bad architecture". Given that it would not take much of your time to polish and refactor such code, I recommend you to always show a quality code for the sake of the followers who lack the coding quality. Keep it up
@funfunfunction
@funfunfunction 6 жыл бұрын
It's also code about burgers. :) This is example code bent to illustrate certain points. Real production code has massive amounts of noise (and is honestly often not perfect either) and would not serve to achieve the goal of the video.
@majorbadidea
@majorbadidea 6 жыл бұрын
Fun Fun Function yes but the lets could have been consts and the formatting could have been prepared
@wonderingAroundtoNoWhere
@wonderingAroundtoNoWhere 6 жыл бұрын
Methew Barbara i have to see the code, but i am kinda sure you are not right, because that's not how it work, you keep the noise out and focus on the topic, it is hardest things to do, i am learning my self hard way which code to use and which one not to use. And when it comes to JavaScript the whole world is up side down, because things are so inter connected, So in short they probably use the right code for the topic which they are covering.
@chrsolr
@chrsolr 6 жыл бұрын
Quick question. How's easier/better to do error handling with promises? How about try/catch? Am I missing something?
@modernclics
@modernclics 6 жыл бұрын
It's actually really simple and it encourages you to catch errors: someAsyncFunction() .then(result => {}) .catch(error => {})
@TedHopp
@TedHopp 6 жыл бұрын
David was struggling to find the words to laud recursion. Perhaps this (anonymous?) aphorism will do: "To iterate is human; to recurse, divine."
@vzsshadow3141
@vzsshadow3141 6 жыл бұрын
at 12:00, if i see well then recursive call inside of then, right?
@brenton8568
@brenton8568 6 жыл бұрын
The implementation of `waitForEach` isn't equivalent to the async/await example. In the async/await version the `processFunc` is only called for each item *after* the previous item has been processed. But the `waitForEach` version calls `processFunc` on every item in the list immediately. This is because the recursive case is calling `waitForEach` eagerly instead of lazily. This can be fixed by wrapping the `then` in a function. e.g. `processFunc(head).then(() => waitForEach(processFunc, tail))`. Alternatively, a reduce can be used and the explicit recursion avoided entirely. e.g. `const waitForEach = (processFunc, items) => items.reduce((acc, item) => acc.then(() => processFunc(item)), Promise.resolve());` This has another advantage - it returns a promise that is resolved when all of the processing is complete! (It also avoids people complaining about the potential stack overflow with recursion ;))
@AngusMcIntyre
@AngusMcIntyre 6 жыл бұрын
Brenton Alker I believe this is incorrect. The n+1th item is only processed when the nth item has completed. This is achieved by start a continuation with .Then(). Continuations do not execute until the antecedent completes. It is not just a fancy wait. It is synonymous with Bind in the monad pattern.
@gasjack
@gasjack 6 жыл бұрын
I had the exact same thought. In fact, I don't think the refactored example would even run, since .then() takes a function, but in the refactor, it is handed the result of calling waitForEach (which is a Promise)
@brenton8568
@brenton8568 6 жыл бұрын
Angus, I'm not sure which part specifically you believe is incorrect. The async/await example at 09:00 behaves as you say - it only processes the n+1th item after the nth item has finished processing. But the "waitForEach" version at 12:00 will start processing all items immediately and doesn't care when they finish. As my comment says - if you want the same behaviour as async/await, you need to delay the processing by wrapping it in a function (continuation). ".then" doesn't create a continuation, it takes one and runs it, the code shown doesn't give it one it gives it a promise (which is already executing - promises are eager). Here is a repl.it session with all 4 versions, you can see the difference in behaviour in the buggy version compared to the others - repl.it/@tekerson/Is-async-await-useless
@brenton8568
@brenton8568 6 жыл бұрын
Rasmus Vestergaard Hansen, you're right, yes, it is passing it a promise instead of a function, luckily (I guess) the spec says that if you pass anything that's not "callable", then it will just treat the identity function as the argument (ie. that step in the promise chain will just pass its value through) - www.ecma-international.org/ecma-262/6.0/#sec-performpromisethen e.g. This produces "Hi!" even though the first `.then` isn't a function. `Promise.resolve("Hi!").then(false).then(console.log);`
@AngusMcIntyre
@AngusMcIntyre 6 жыл бұрын
Brenton Alker I see it now. Thanks for the explanation. Well spotted!
@smilebagsYT
@smilebagsYT 6 жыл бұрын
First thought before watching: No, no it isn't. Let's see if I change my mind!
@smilebagsYT
@smilebagsYT 6 жыл бұрын
Well, I didn't change my mind but it was a good look into why I believe async/await syntax is beneficial. Great video, thank you!
@benjaminmosnier
@benjaminmosnier 6 жыл бұрын
I was exactly thinking this way... but I have to admit the last example showing recursion is very clever
@vlad981
@vlad981 6 жыл бұрын
yeah, I think it's too much clever) We should use easiest solution possible, and async\await is definitely makes code easier to reason about.
@AngusMcIntyre
@AngusMcIntyre 6 жыл бұрын
Iron Candy the language shouldn't be holding your hand?!? That is exactly why we have languages. Would you prefer doing it all in assembler?
@smilebagsYT
@smilebagsYT 6 жыл бұрын
I must disagree. Async/await encourages readable code. Whether the developer decides to write convoluted, long functions is unrelated. Async/await only seems to take away the understanding of what's really happening, only until they try actually doing something with it. You need to understand promises to use async/await effectively. Syntactic sugar is syntax. Syntax which makes things easier is a good thing.
@danilocecilia7831
@danilocecilia7831 6 жыл бұрын
oh... im sorry I didn´t get the explanation of the loadallusers, where that ProcessFn comes from?
@paolodisintegra
@paolodisintegra 6 жыл бұрын
Why do we have to hate ourselves and use promises when we can enjoy some simple async await and invest our time on more fun stuff 😄
@illuminatiZ
@illuminatiZ 3 жыл бұрын
It is pure intellectualism. but when you must code and have no time, it is time to code async/await.
@sohamchauhan4372
@sohamchauhan4372 5 жыл бұрын
Variables in promises are scoped and not available to outer scope. For example, const user = User.find({id: 'some id'}); const admin = Admin.find({id: 'some id'}); if(user.name === admin.name) { // do something} else{ // do something else} How can this be implemented with Promises?
@fishfpv9916
@fishfpv9916 5 жыл бұрын
What is your thought on combining promisies and asynchronous await. I have used it to push several network requests to an earray then calling await on the Promise.all before moving on the the next step of the function.
@lnr124
@lnr124 6 жыл бұрын
Is there a typo on line 11 of your rewrite? Should it be processFunc not processFn? Or I am reading it wrong?
@DavidWMiller
@DavidWMiller 6 жыл бұрын
You are, it's the argument, named on line 8.
@OkanEsen
@OkanEsen 6 жыл бұрын
Yeah but I guess the purpose of the video wasn't really about "correctnes" but rather to get the point straight and therefore more like pseudo code.
@ChrislyBear
@ChrislyBear 6 жыл бұрын
Probably a typo.
@VanjaMk1
@VanjaMk1 6 жыл бұрын
Yeah, that tipped me off too. A typo. Good thing I searched the comment thread before posting it ;)
@benbanda07
@benbanda07 6 жыл бұрын
Where I used async/await the most, is with mongodb, when I need some arrays from differents collections (example: user, appointments, profesional and service) and if I had used promises, I would have had a "promise hell"
@funfunfunction
@funfunfunction 6 жыл бұрын
We discussed this in the forum, and we concluded that it works fine with promises if you do the same thing that you technically do with async await, and just collect stuff in a closured variable: const displayAccountAndContacts = accountName => { let account return fetchAccountByName(accountName) .then(loadedAccount => { account = loadedAccount return fetchContactsByAccountId(account.id) }) .then(contacts => { console.log(`${account.name} (${account.id})`) contacts.forEach(contact => console.log(` - ${contact.fullname} (${contact.job_title})`)) }) .catch((error) => { console.error(error) }) } Alternatively, you can build up the result gradually: const displayAccountAndContacts = accountName => fetchAccountByName(accountName) .then(account => fetchContactsByAccountId(account.id) .then(contacts => [ contacts, account ])) .then(([ contacts, account ]) => { console.log(`${account.name} (${account.id})`) contacts.forEach(contact => console.log(` - ${contact.fullname} (${contact.job_title})`)) }) .catch((error) => { console.error(error) })
6 жыл бұрын
I find generators with "co" library to be more powerful than async-await, as execution can be cancelled after some step. But 9/10 times I rather write an async function, as no additional library needed and would be easier to understand for others.
6 жыл бұрын
Well, most libraries you can implement yourself in a rather quick time. But using something field-tested is most of the time better.
@pepkin88
@pepkin88 6 жыл бұрын
Yes, this. And also nice and intuitive abstractions of yielding arrays and objects. Plus support for thunks, which are just old style Node functions, partially applied with Function#bind.
@allan2932
@allan2932 6 жыл бұрын
As I see it Promises is the JS functional way of doing async programming. It can be used together with functional techniques like currying and point-free programming. I prefer this style but if you are more into imperative programming async await is probably easier to reason about. The point with the SQL example that used recursion was also that the "waitForEach" function most likely could be found in any functional library and therefore you probably wouldnt have to write it in the first place if you were doing functional programming. If you dont have to write that function then that example get easier to understand than the async await one. Also, in order to have error handling with async await you need to place it in a try catch and that is not very nice code to look at compared to a catch I think. Its true that aync await have less nesting but if you more than 1-2 levels of nesting with your promises you should probably rethink your architecture anyway
@SumTsuiTechie
@SumTsuiTechie 6 жыл бұрын
surprise this comment didn't get a lot thumbs ups
@PeerReynders
@PeerReynders 6 жыл бұрын
Seems some people overlook that having learnt how to wrangle promises is beneficial practice for when you later need to learn how to wrangle observables (RxJS or tc39/proposal-observable). I suspect that the recursive solution at the end was a cliffhanger to talk about for-await-of which is included in ES2018 (tc39/proposal-async-iteration). async function main() { const users = [ { id: 1, delay: 1000 }, { id: 2, delay: 300 }, { id: 3, delay: 500 } ]; for await (const x of users.map(processUser)) { console.log(`done: ${x}`); } } // Output: // start: 1 // start: 2 // start: 3 // resolve: 2 // resolve: 3 // resolve: 1 // done: 1 // done: 2 // done: 3 const processUser = ({ id, delay }) => { console.log(`start: ${id}`); return new Promise((resolve, _reject) => { fakeProcessing(resolve, id,delay) }); }; const fakeProcessing = (resolve, id, delay) => { const resolveIt = () => { console.log(`resolve: ${id}`); resolve(id); }; setTimeout(resolveIt, delay) } main();
@PeerReynders
@PeerReynders 6 жыл бұрын
I never implied that observables are a "one size fits all" solution. I'm not Netflix: Promise to not use Promises - ES7 Observables by Brian Holt kzbin.info/www/bejne/epKmlGuimNCorZo I was thinking more about enriching one's toolbox, broading one's skillset to be more prepared for upcoming challenges. Most button-click examples are just a "Hello World" equivalent and not really representative of effective use cases for observables (though the throttle and debounce operations seem to be popular with click event sources; see "ReactiveX RxJS Manual Overview Flow" example) In terms of UI "drag and drop" would probably be a better example. Processing (and filtering) data coming in over one or more WebSockets at unpredictable intervals would be a much better example but would already require a some basic understanding of working with event streams. Even Ben Lesh (RxJS lead) admits that understanding observables is rarely "easy" in the beginning. kzbin.info/www/bejne/emisnpmDbMSgmdU "The introduction to Reactive Programming you've been missing" by Andre Staltz is one of the better introductions. Observables primarily exist to make dealing with repeating events (event streams) easier. This is accomplished by moving away from "program statements defining a sequence of steps to be taken" and moving toward "data traversing a pipeline of composed operations which transform the data by applying expressions". It's a programming style where you structure the flow of data, not the flow of control. It's a different way of composing logic that relies on composing operations and expressions rather than composing statements. Promises and observables are strangely similar even though they are different: - A promise value/error pushes through the chained handlers as soon it is settled (i.e. it's eagerly evaluated), while observable events are pushed through the operators only when at least one subscriber is listening for events (i.e. they are lazily evaluated). - A promise settling is like an "event" but by design the "stream completes" after that single event - so conceptually it is a "single event stream". Because promises can only be settled once, it is possible to retrofit imperative programming constructs in an async, await, or for-await-of style which tends sweep the promise's asynchronous nature under the rug (for better or worse). A promise handler chain clearly focuses on the sequence of composed transformations that occur when/if the value/error becomes available.
@gillianbc
@gillianbc 4 жыл бұрын
Sorry if this is a dumb question, but in the refactored code, line 11, what is processFn?
@TheMrChugger
@TheMrChugger 6 жыл бұрын
That final recursive solution makes me feel so dumb. I mean I understand it entirely, but I'd never have dreamed of writing it like that. Beautifully done.
@nloomans
@nloomans 6 жыл бұрын
Wait... why didn't you use `Promise.all` in 12:30?
@louisvno7649
@louisvno7649 6 жыл бұрын
Noah Loomans yea i'm also wondering
@louisvno7649
@louisvno7649 6 жыл бұрын
I guess they wanted to replicate exactly the behaviour of the asnyc/await version of the code
@funfunfunction
@funfunfunction 6 жыл бұрын
That would change the behaviour of the code
@ChrislyBear
@ChrislyBear 6 жыл бұрын
Question: If you have an async that functiu that uses await and you want to call this async function from elsewhere, do you have to call it using await again? And if so, then the calling function will also have to be async again, right? So, how far up the call stack do you have to sprinkle the async/await? All the way?
@funfunfunction
@funfunfunction 6 жыл бұрын
An async function returns a promise.
@vzolin
@vzolin 5 жыл бұрын
So using with is almost obfuscated code is better even if it doesn't offer any performance improvement?
@jasonmcintosh2632
@jasonmcintosh2632 6 жыл бұрын
Doesn't recusion place a big load on the stack which ends up being much slower and more resource hungry?
@mrjosephDJ
@mrjosephDJ 6 жыл бұрын
Can you paste a copy of the object that is returned from the db.query just as a example?
@phimuskapsi
@phimuskapsi 6 жыл бұрын
One nice thing about async/await is that the async function is automagically wrapped in a then/promise. This means that from a synchronous function you can call an await function and do a then and the async will return data.
@voifusgaton
@voifusgaton 6 жыл бұрын
The `processAllUsers` translation is not correct. `waitForEach` calls `processFunc` over all inputs instead of waiting for the first promise to resolve before calling it over the second input. Additionally, `waitForEach` is not generic, as it will short-circuit if you attempt to use it over an array of booleans, numbers that might be 0, possibly empty strings, or any array of possibly falsy values. Given that it behaves in the way I just described, it might as well just be defined as: `const waitForEach = (fn, vals) => Promise.all(vals.map(fn)).then(() => {});`
@bunglegrind1
@bunglegrind1 5 жыл бұрын
I prefer the third way: working with asynchronous libraries such as Douglas Crockford's parseq or nodejs async. I tried to implement the example using parseq (hopefully without errors...) - For the sake of brevity, async requests are not supposed to return an error. The function returns a "requestor" - for more info check Crockford website or his latest book. pastebin.com/embed_js/ZEhSP6PU
@LadyofBakerStreet
@LadyofBakerStreet 5 жыл бұрын
do we know of a functional promise library that has a waitForEach equivalent ?
@OliverLonghi
@OliverLonghi 6 жыл бұрын
You can use functional programming to iterate over returned array (after async/await db consult) as well, don´t you?
@CPlayMasH_Tutoriales
@CPlayMasH_Tutoriales 6 жыл бұрын
Maybe with simple examples promise-based code is better, but when you have complex logic with lot of edge situations to be handled, then async-await is way better for readability and productivity
@julianpinn5018
@julianpinn5018 4 жыл бұрын
Conclusion: async/await results in clear and powerful code that is still readable when revisited in the future.
@adrianli7757
@adrianli7757 6 жыл бұрын
When I'm trying to decide whether or not one bit of code is better than another. I always ask the question: which piece of code will take less time for a beginner to understand? Sometimes I still use Promises instead of async/await (depending on the use-case), but for most of these examples, I think it fails to show the benefits of plain Promises instead of async/await.
@GreenZ3r0
@GreenZ3r0 6 жыл бұрын
Your db example can be a lot shorter if you use Promise all and array map. ( return Promise.all(db,query(...).map(u => processUser(u.id))) )
@okaybenji
@okaybenji 6 жыл бұрын
great video! i was convinced async/await was useless, but these examples actually convinced me i was wrong. is there a way to tell, before reaching for promises, that the problem you’re working on might be one async/await is better suited to solve?
@loolog
@loolog 6 жыл бұрын
I noticed there might be a problem with the recursion code in the example starting 10:18, other than the `processFunc`/`processFn` typo, and sure enough it doesn't do what you intend to (probably because of a typo too): gist.github.com/googol/83577cab537656ea9a4d3ea745d5e70f
@gasjack
@gasjack 6 жыл бұрын
Yep, noticed the same thing when watching - was too lazy to try it out though :-)
@andzrit
@andzrit 6 жыл бұрын
There are some differences in syntax but I thought the key difference between async/await and promises is that await is similar to generator function/yield in such that you can stop and iterate. Await will always return a promise object too, so it really seems like apples and oranges. Am I wrong...?
@MattFarmerdotnet
@MattFarmerdotnet 6 жыл бұрын
In my experience the one thing that is easier to program correctly using async/await is when part of your code `throw`s before you return your promise. See this example: // Common methods function getConfig(key) { throw new Error('Key Not found'); } function someAsyncMethod(data) { return Promise.resolve(data); } // Implementations function promiseVersion() { return someAsyncMethod(getConfig('someKey')); } async function asyncVersion() { return await someAsyncMethod(getConfig('someKey')); } // Show Differences // Throws an error, error handler is not called promiseVersion().then( s => console.log(s), e => console.warn(e) ); // Error handler is called asyncVersion().then( s => console.log(s), e => console.warn(e) )
@krzysztofkk6964
@krzysztofkk6964 6 жыл бұрын
Why are you processing users sequentially instead of in parallel (that way you should get the overall result quicker) ?
@funfunfunction
@funfunfunction 6 жыл бұрын
Because it's a made up example to illustrate sequential processing. :) In real life, you might want to do sequential processing because not all users could be loaded into memory at the same time, let's say 40 million users perhaps.
@krzysztofkk6964
@krzysztofkk6964 6 жыл бұрын
Fair point. Thanks FFF :)
@SherazAli-ky1kn
@SherazAli-ky1kn 5 жыл бұрын
Nicely explained. But, I was expecting you guy would draw a comparison in terms of performance. Or Its just same in both cases?
@OhhBabyATriple
@OhhBabyATriple 5 жыл бұрын
Poor example at 9:16 adding the await in the for of loop is actually slowing execution. There is no need to wait for the result of the processUser function, therefore we do not need the await. If the processUser function uses an external rate limited service that should be handled in the processUser function rather than improperly awaiting unnecessarily
@funfunfunction
@funfunfunction 5 жыл бұрын
Yeah, but we cannot just change the code to do something else when we are comparing syntaxes. :)
@jonas-mm7em
@jonas-mm7em 6 жыл бұрын
I'm wondering why your variables are not const instead of let in your first example of async/await? EDIT: As well why not using Promise.all instead of waitForEach function? In the latter you are cascading your async operation rather than running them in parallel with something like db.query(sql, []).then(users => users.map(user => processUser(user.id))).then(userPromises => Promise.all(userPromises)). I find it even easier to reason about, what do you think? Is the cascading supposed to be required by the way processUser is supposed to work?
@funfunfunction
@funfunfunction 6 жыл бұрын
No particular reason for the first one, its just not relevant to the topic at hand. Using Promise.all would have changed the logic of the code. The point of the example is to show sequential processing. :)
@jonas-mm7em
@jonas-mm7em 6 жыл бұрын
Of course you are right. It is not relevant to the topic at hand. I just wondered if there was a particular reason. :) Alright I get it for the sequential processing, you are right indeed. I didn't think sequential processing was to be kept. Now I get it why your waitForEach function is such a nice way to do it. Thanks for the clarification. ;) Have a great day.
@FirstLast-rb5zj
@FirstLast-rb5zj 5 жыл бұрын
The issue isn't strictly level of nesting. It's taking a block of code and having to split it. That can add nesting but it can also result in a string of a lot of functions more than you would need with it difficult to divine flow between them. This is what is meant by the spaghetti of callbacks. It's all a moot point. Promises and async/await are neither compatible nor interoperable with callbacks so you have to stay with callbacks. They both actually do things slightly differently to callbacks and if you keep using them instead of callbacks as though they're the same you'll end up writing broken code. Promises and await/async are for the parallel processing. Your wait for each function can actually break if it's not using callbacks if first come first serve. However you're just looping the users one by one.
@giovannipds
@giovannipds 6 жыл бұрын
Hello! Just watched this while going to work by bus. So yes, it is useful, and it's was very interesting to see that, if we don't arquitecture our code well with promises, we can easily fall into a callback hell. That for with const bugged me. Does that really work? 9:46. I've always thought that there it must be a let, 'cause it will use the same var scope over and over again. Am I wrong? Why const there??? Howww?! O.o
@PauloBrumatti
@PauloBrumatti 6 жыл бұрын
Giovanni Pires da Silva it actually recycles the variable every time the for runs, not only it's value. Therefore, the variable isn't "reattributed" on every run, rather it's trashed and created and that's why const works, since it's block scoped
@giovannipds
@giovannipds 6 жыл бұрын
That's very weird, I always thought that the variable was created once and its value was only reset at each loop. O.o I wonder how many languages use the same approach now... ps.: thank you!
@PauloBrumatti
@PauloBrumatti 6 жыл бұрын
Giovanni Pires da Silva that was how "var" used to work. Since let and const are block-scoped, they only live while their own block lives.
@giovannipds
@giovannipds 6 жыл бұрын
Right. Thanks again. =]
@LucasVieira42
@LucasVieira42 6 жыл бұрын
Don't be clever, write stupid code. You can write stupid code using Promises, I think you missed the opportunity to show it on this video. Stop this ternary madness (:
@bjornkihlberg2103
@bjornkihlberg2103 6 жыл бұрын
async/await is an idea from Haskell. You could imagine something that is to I/O what async/await is to promises. Let's call it do/read or something along those lines. The same way async/await allows you to see on a function if it somewhere contains promises, do/read would allow you to see on a function if it somwhere contains I/O. Example async/await async f() { const x = await api.getUsers() } Example do/read do f() { const x = read console.readLine() }
@DavideOrazioMontersinoPlus
@DavideOrazioMontersinoPlus 5 жыл бұрын
Also ternary expressions. Might be useful sometimes, but if you are indenting your code, then your expression is too complex and plausibly could get changed in the future. Probably you'll have to change to an if / then statement (for declaring variables, for breakpoints and debugging, whatever).
@carloscaleroflores4358
@carloscaleroflores4358 6 жыл бұрын
The act of destructuring the array is called Pattern Matching just a little FYI there :)
@ThePapanoob
@ThePapanoob 6 жыл бұрын
Why arent you using Promise.all? This would make alot more sense in the db example
@dipunm
@dipunm 6 жыл бұрын
I wonder if you noticed that your last example was not the same? The functional version runs in parallel because you execute the recursion before the then call and pass the Promise to the then function. We could achieve the same with async await by using `await Promise.all(users)` but if there are side effects, you have a bug that you potentially missed.
@giladierez
@giladierez 6 жыл бұрын
Agree there seems to be a bug there.... If you think about, this is actually a good example why Async Await are needed in the language :)
@qwarlockz8017
@qwarlockz8017 5 жыл бұрын
Yeay! I love the opening ! I have seen a few eps where it was not there and I sooo always miss it!
@LarsGyrupBrinkNielsen
@LarsGyrupBrinkNielsen 6 жыл бұрын
7:15 getHamburger with error handling and less nesting: const getHamburger = (server, defaultBurger) => server .hasBurgers() .then(hasBurgers => hasBurgers ? server.getMaxNumberOfBurgersPerDay() : Promise.reject()) .then(maxBurgers => getNumberOfEatenBurgersToday() < maxBurgers ? server.loadBurger() : Promise.reject()) .catch(() => Promise.resolve(defaultBurger));
@JlNGLEZ
@JlNGLEZ 6 жыл бұрын
I'm glad you mentioned error handling - I find when making any more than 3 calls within an async function is where it shines - wrapping the initial function call in a try catch for error handling - it's very easy! I do agree with the fact that it does steer people away from understanding the true functional programing - but when you're in a team of developers I'd argue that it's easier to read and understand the async/await decorators then it is to read and understant a recursive functional statement - love the videos though keep it up!
@sirynka
@sirynka 6 жыл бұрын
[head, ...tali] = [0, 1, 2, 3] i kind of understand how does it works, but where can i find more info about this strange and nice looking thing?
@adammoefoe
@adammoefoe 6 жыл бұрын
Once I understood async/await and used it, I found it hard to use normal promises without hitting myself. I enjoy the synchronous look, and that I don't have to ever explicitly create promises because async guarantees promise return. The only time I use .then and .catch now is when I'm dealing with a single promise, otherwise it's try catch with async/await.
@simoneicardi3967
@simoneicardi3967 6 жыл бұрын
[OT - Maybe an idea for next episodes] - ES6 Keyed collections: Maps, Sets, WeakMaps, WeakSets. What do you think about? Could it worth talking about them? Tnx!!
@andrejbartko
@andrejbartko 6 жыл бұрын
I don't know. perhaps I'm biased. I buy it in the first example although I would write it differently. In the second example, the recursion is just easier to read for me. If I see more than 3 times async / await in the code it just gets harder to figure out the logic, while if it is done as promise chain or observable pipe it is clear.
@TheCodingTeacher
@TheCodingTeacher 6 жыл бұрын
Homie, that rewrite not using the ternaries is not AT ALL equivalent to the initial code. You are returning defaultBurger from inside the promise, which is NOT the same as returning defaultBurger from the root scope of the async function, as it was in the beginning. In essence, the original code had fallback statements returning defaultBurger, but yours evaluates to undefined.
@josemaenzo
@josemaenzo 6 жыл бұрын
Is server.loadBurguer() synchronous?
@vladyslav4
@vladyslav4 5 жыл бұрын
about waitForEach example - if you head ever happens to be 0 (which is absolutely valid element in arbitrary array) you code breaks. same for empty string, null, undefined or false. any of those could be elements of arbitrary array
@vladyslav4
@vladyslav4 5 жыл бұрын
so since you don`t have any way of checking end of array by looking at head, you actually have to use index and array length.
@ekhmoi4552
@ekhmoi4552 6 жыл бұрын
I would curse so bad if I took over a project where previous developer decided to use recursive functions instead of readable code just to feel "satisfied"
@chanlito_
@chanlito_ 6 жыл бұрын
click baited
5 жыл бұрын
I found a very useful function of async/await Let's think of this scenario: I've got a "route" treatment in express that calls an asynchronous function: The only way I found to deal with that asynchronously was passing "res" to the function in order to it to respond to the client. I HATED THIS. So I need to promisify the async function so it's the "route function" the one who responds and I don't have to pass "res" to other level. (I know I'm not quite clear so I give an example: app.get("/save", (req,res) => { saveFile(req.fileName, req.data, res) }) function saveFile(fileName, data, res) { fs.writeFile(fileName, JSON.stringify(data), (err) =>{ if(err) res.send({saved: false, err: err}); // .status(404) res.status(200).send({saved: true}); }); } I hope this'll serve for you to see my point) Once again: thanks MPJ for your great job
@Misantronic
@Misantronic 6 жыл бұрын
after working productively with async await for about a year now, I see absolutely no reason to use Promises ever again. the only case is, when a function needs to be async and has to `return new Promise(resolve => ...)`
@JlNGLEZ
@JlNGLEZ 6 жыл бұрын
line 5 - @17:50 - where's the processUser function ay!
@MikeMcLin
@MikeMcLin 6 жыл бұрын
It’s killing me that we are staring at this code snippet that has a glaring bug in it. "processFn" is not a function.
@Luxcium
@Luxcium 5 жыл бұрын
What makes JS so amazing is its capacity to be used in so many different ways thanks for sharing with us this view on JS
@MiChAeLoKGB
@MiChAeLoKGB 6 жыл бұрын
The only reason I find aysnc / await useless is, that my JS has to run in browser (no fancy shmancy node.js) and its not supported in IE 11 which I still have to support. At least I got my boss to agree with me and drop support for IE 10 last week, so now I just have to wait few years for IE to disappear completely and be able to use somewhat new JS stuff. Other than that, this video probably sold the saync / await even more :D
@MiChAeLoKGB
@MiChAeLoKGB 6 жыл бұрын
Id like to, but I can't. The company I work at, well its basically only the boss, just avoids any new stuff, like SASS or Babel or any CI/CD etc. If he wont give in, I will probably just leave tho. I did get in some new things, but it was usually by me just doing it and telling him when it was one :D Thats how I partially got in SASS at least for our front-ends...
@MiChAeLoKGB
@MiChAeLoKGB 6 жыл бұрын
Yeah, that's what I did with SASS. I really have to push in some sort of CI/CD, like buddy.works or even gitlab hooks, so the babel and SASS gets compiled automagically. The issue is, my boss likes to work on live versions on the server. If I had any real time to do so, I probably would, but he is refusing to hire somebody, because he wants us to have more work than we can comfortably handle (so you end up switching even 4 projects a day), because it keeps us on our toes :D But as I said, I will try to push in buddy or something similar and it that wont happen, Ill just probably go. I want to learn and use new stuff, not only hear/read about it, without even trying it that much, because I just don't want to see any code when I get home... I guess I'll just stop talking now...
@dungandonuts
@dungandonuts 6 жыл бұрын
For the processAllUsers example, you basically implemented reduce with recursion! I can see why you might want keep the waitForEach function separate since it's useful in a variety of cases too though. users.reduce( (acc, curr) => acc.then(() => processUser(curr.id)), Promise.resolve() ))
@Psinite
@Psinite 6 жыл бұрын
Your example serialises all async processUsers. It would be better to reduce it into an array of promises that you then cast promise.all on.
@dungandonuts
@dungandonuts 6 жыл бұрын
psi I think the example in the video runs them in sequence but that's a good point, you could map processUser over the users and then run Promise.all on the resulting array to run in parallel. Some promise libraries also have a "sequence" function so you could also use that if for some reason they needed to be in sequence.
@FlyingOctopusKite
@FlyingOctopusKite 6 жыл бұрын
😊 good video. Was a fun thread and challenge. One key thing is that you should understand promises to use async / await. One thing I like about promises is you don’t have to make up your own implementation for error handling, promise catches can be tricky but you can do useful things with them in a system. Not having error handling is like making an http call and always expecting a response.
@kmikce69
@kmikce69 6 жыл бұрын
Hi! Your videos are awesome!! I have been working 2 years with Javascript but my brain is going to explode with the code shown in the min ~10:30 when you use the recursion stuff to make this more clever... Could you please that code to me (for dummies it would be nice haha) ?? I am trying to debug it in my mind but I get stucked. Thank you even if you could waste some minutes to it or not, I love your videos anyway :)
@kmikce69
@kmikce69 6 жыл бұрын
Specially the [head, ... tail] and their flow into the recursion...!!
@funfunfunction
@funfunfunction 6 жыл бұрын
The code is based on a recursive function. If you find recursion hard there is a recursion video explaining the basics. It's weird as hell if you're not used to it but pretty normal to functional programmers. The ... is unrelated to recursion and is a separate thing - google array spread.
@ColinRichardson
@ColinRichardson 6 жыл бұрын
Await functions are promises, Promises can be "awaited" for.. Just use which ever makes the most sense. Only time I think it looks a little ugly is if you want to do something in parallel. const [value1, value2] = await Promise.all(asyncFunction1(someArgs1), asyncFunction2(someArgs2)); And to be honest, even then, it's very acceptable, especially if there are variables above the promise all that you need to re-use again.
@microcontrolledbot
@microcontrolledbot 6 жыл бұрын
async / await is one of the best features ever added to node. I think mysql and request packages needs to get their ass in gear and return promises when no call back function is specified so a wrapper is not needed.
@argyleink
@argyleink 6 жыл бұрын
I feel like Promise.all() was missing, especially in the processAllUsers example
@retiar2111
@retiar2111 6 жыл бұрын
I just thought about error handling. Taking your word for nexts week episode :D
@pepkin88
@pepkin88 6 жыл бұрын
I would prefer Array#reduce rather than an additional function for that. users.reduce((promise, user) => { return promise.then(() => processUser(user.id)) }, Promise.resolve()) But I would prefer yield/await syntax instead of pure promises (and LiveScript instead of JS).
@MrGrokku
@MrGrokku 6 жыл бұрын
I think there is an inverse correlation between cleverness and readability. If you had a big application in production written as the first promise example it would be hell to understand, and new developers, especially the ones with less experience, would have to be handheld for a long time before they could participate in production. Ternary operators help making that worse. In my opinion, if you have to chain function calls on either side you should just use a conditional block. On the promise examples, I think they miss the ability to return a value from inside a promise's then instead of creating and nesting another promise inside it, and also the ability to simply pass the function that will handle the next step, defined elsewhere, which would be a little more functional. Personally, I don't like "async / await", but mostly because then you have to use "try / catch" blocks which end up cluttering the code even more, but that is not an informed opinion, I haven't worked with it enough to have an opinion on the topic.
@jondreauxlaing
@jondreauxlaing 6 жыл бұрын
It's too bad that Promises aren't actually monads, because there could have been a much more generic async/await solution like do notation in Haskell. This sort of thing seems to plague the JS community where overly specific, yet easy solutions dominate over generic, and slightly harder solutions. That was kind of the issue that created Promises in the first place. If the JS community at large was cool with main-stream monads, then this issue probably could have been solved a while ago. Instead now we have new keywords for dealing with mapping and binding not-quite-Monads, which only work in those scenarios. I'll admit, I've never gotten a chance to use async/await since it's too bleeding edge for most of the professional projects I've worked on, and I'm not excited enough about it to use it in personal projects, but I do wonder how error handling is done. Like what happens when you await on a call that fails? Do you just get an exception thrown? That doesn't seem to solve the problem imho.
@nickngqs
@nickngqs 6 жыл бұрын
yeah you can throw an exception by your self and use try catch in the await. tbh i think handling errors in async/await is more elegant than full on promises?
@AngusMcIntyre
@AngusMcIntyre 6 жыл бұрын
Can you describe what it is about promises that are not completely monadic? I'm currently wrestling with the pattern and am curious!
@jason_v12345
@jason_v12345 6 жыл бұрын
If a language feature obviates the need to "bother" learning something more complex, doesn't that fit the very definition of "useful"?
@funfunfunction
@funfunfunction 6 жыл бұрын
It doesn't doesn't do that, though. If you don't understand promises, you should really not be using async / await yet,
@tahoemph
@tahoemph 6 жыл бұрын
Like others I find the burger example wanting. But for another reason. It is racy. You ask the server if it has burgers and then you do some things asynchronous to whatever the server is doing and then you assume if earlier the server has burgers it still does. This is wrong no matter how you structure the code. I think most people would read user processing better as a loop and as soon as you start attempting to emit messages in a manner separate from the messages and/or gather up a list of success/failures to be displayed the waitForEach version starts involving more complexity in the shape of closures. Maybe old lispies would like this version better but then you should rename head/tail as car/cdr then. I think you should really ask a different question from "Is async / await useless". Instead ask "when is promises best and when is async / await best". Near the end you mentioned that async / await shines when you are gather up stuff. So a sequence of code that looks like "get a, based on a get b, based on b get c, ...'. Concretely maybe 'get user, get users profile, get users avatar, etc., return the enhanced user object'. One places where promises shine is when you wan to fire off a bunch of activity and then block on all or part of it being done. I think in order to make good use of async / await you are going to have to understand how promises work and it would be criminal if you use promises not to understand when async / await makes your code look cleaner.
@daviddesmarais-michaud4345
@daviddesmarais-michaud4345 6 жыл бұрын
Async/await has performance benefits. I used to think that the abstraction would have some overhead cost on top of promises, but in actuality, what it allows for is to not have promises chained in memory and therefore allows for more effective garbage collection and more stable performance. async/await is great. But people should understand callbacks/promises/generators before using them or else they won't ever understand the underlying nature of javascript
Dependency Injection basics- Fun Fun Function
22:26
Fun Fun Function
Рет қаралды 153 М.
Generators in JavaScript
22:16
Fun Fun Function
Рет қаралды 49 М.
Chain Game Strong ⛓️
00:21
Anwar Jibawi
Рет қаралды 41 МЛН
How Strong Is Tape?
00:24
Stokes Twins
Рет қаралды 96 МЛН
Mom Hack for Cooking Solo with a Little One! 🍳👶
00:15
5-Minute Crafts HOUSE
Рет қаралды 23 МЛН
Async + Await in JavaScript, talk from Wes Bos
15:52
freeCodeCamp.org
Рет қаралды 118 М.
Now I Know Why Most People Don’t Use gRPC
19:11
ArjanCodes
Рет қаралды 59 М.
Async JS Crash Course - Callbacks, Promises, Async Await
24:31
Traversy Media
Рет қаралды 1,4 МЛН
Iterators in JavaScript using Quokka.js
21:07
Fun Fun Function
Рет қаралды 111 М.
Object-Oriented Programming is Bad
44:35
Brian Will
Рет қаралды 2,3 МЛН
var, let and const - What, why and how - ES6 JavaScript Features
19:19
Fun Fun Function
Рет қаралды 181 М.
Microservices are Technical Debt
31:59
NeetCodeIO
Рет қаралды 687 М.
map for async iterators in JavaScript
25:59
Fun Fun Function
Рет қаралды 19 М.
So You Think You Know Git - FOSDEM 2024
47:00
GitButler
Рет қаралды 1,3 МЛН
Why Isn't Functional Programming the Norm? - Richard Feldman
46:09
Chain Game Strong ⛓️
00:21
Anwar Jibawi
Рет қаралды 41 МЛН