forEach is BAD! for Async Await Code | Advanced Async/Await Javascript Tutorial

แชร์
ฝัง
  • เผยแพร่เมื่อ 15 ต.ค. 2024

ความคิดเห็น • 248

  • @DaveGrayTeachesCode
    @DaveGrayTeachesCode  2 ปีที่แล้ว +28

    forEach is not the right choice for Async / Await code. In this tutorial, you will learn about 4 alternatives to forEach that will work when you are writing async code. If you are just starting out with Javascript, I suggest my full 8 hour Javascript tutorial here: th-cam.com/video/EfAl9bwzVZk/w-d-xo.html

    • @ocoolsanni2803
      @ocoolsanni2803 2 ปีที่แล้ว

      Thanks for the tutorial and the info I've been looking for... I've got a question since I'm more interested in the reduce function and I'd love to try it out. How would you slower it when web scraping?? Would you use the timeout function since JavaScript doesn't have a sleep function??

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      @@ocoolsanni2803 I'm not sure how this applies to web scraping. You can use an interval in JS to time the requests if needed.

    • @ocoolsanni2803
      @ocoolsanni2803 2 ปีที่แล้ว

      @@DaveGrayTeachesCode Thanks for the quick responce and guidence, in an api i'm working on. Looking foward to a scrapping tutorial from you

    • @Gameplayer55055
      @Gameplayer55055 2 ปีที่แล้ว +1

      replacing foreach with for helped dramatically, now my entries don't hang page for 4 seconds

    • @hasithadhananjaya2806
      @hasithadhananjaya2806 2 ปีที่แล้ว

      dear sir, I'm begginer for JS, what is the frame work I should learn first
      NODE or REACT or else.
      Please!.

  • @Cerbeh
    @Cerbeh 2 ปีที่แล้ว +11

    Really cool seeing the reduce example. I recently used it myself to serialise a bulk file upload due to size limits on our API. Had never seen it before and now here you are making a video explaining it too!

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว +2

      And you just described a great use case! Nice! 💯🚀

    • @maestrocode9164
      @maestrocode9164 2 ปีที่แล้ว

      Would a for-of loop do the same? I fail to see the difference

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว +1

      @@maestrocode9164 if you watch the video you will see the for of loop demonstrated as well.

  • @cedigasser
    @cedigasser 2 ปีที่แล้ว +14

    Actualy, await Promise.all() returns an array in which the results are in the same order as the promises they're from. This is usefull if you don't need to wait after each promise but still need them in sequence.

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว +2

      Agreed as discussed in a few of the other comments. 💯

    • @absbica31
      @absbica31 2 ปีที่แล้ว

      @@DaveGrayTeachesCode does this mean line 25 at the end?

  • @Bayo106
    @Bayo106 2 ปีที่แล้ว +2

    as soon as I saw this title I had an epiphany and watching it helped me solve something at work. thank you so much

  • @glennadams8833
    @glennadams8833 2 ปีที่แล้ว +3

    I've struggled to get serialized data from multiple async function calls and this clears up a lot. Aside from when not to use a forEach method, the gem in your lesson is going deeper into async/await and map/reduce methods. Cool!

  • @chriskao1190
    @chriskao1190 2 ปีที่แล้ว

    I falled into this pit once. It took me days to find out the reasons and fix with the for ... of approach.
    At that time not many articles I could find on this topic.
    Thanks for making this video. This really do help.

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      Thank you for the kind words, Chris 🙏 You're welcome! 💯

  • @NguyenNguyen-ek4zq
    @NguyenNguyen-ek4zq 2 ปีที่แล้ว +3

    I enjoy watching the reduce alternative. However, what made me unrest there is the callback of reduce without a return statement. Turns out that with async await and without an explicit return statement, you actually implicitly return a promise resolve undefined. That could have been explained in the video. Anw, thanks for a great video.

  • @lalitpatil7972
    @lalitpatil7972 2 ปีที่แล้ว

    2 days before I was struggling with this forEach with async issue and today I saw your video. Saved my day.
    Thank you.

  • @AntonioSantos-ve6zv
    @AntonioSantos-ve6zv 2 ปีที่แล้ว +1

    Kind of advanced for me at this point, but it's put so clearly I've learned a lot. Thanks!

  • @DebdutBiswasOnline
    @DebdutBiswasOnline 2 ปีที่แล้ว +2

    Awesome, learned a lot. I was facing exactly a same problem to asynchronously send multiple separate emails by iterating an array fetched as database result.

  • @RD-jr8nv
    @RD-jr8nv ปีที่แล้ว

    Reduce is so versatile, can do a million things with it. This was really neat

  • @benarcher372
    @benarcher372 2 ปีที่แล้ว +1

    "To get the job done". Most of the time that's all that matters. Thank you Dave for all your great JavaScript tutorials.

  • @yadusolparterre
    @yadusolparterre 2 ปีที่แล้ว +37

    12:19 You could have refactored your code in a cleaner way:
    const posts = Promise.all(ids.map(getPost))
    No need for an async function if you are not going to await anything

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว +11

      Agreed, but also noting for others reading this that await is needed before the Promise.all. Always improving - while the overall point of this video is solid, the Promise.all part is the area I would refactor. I'd still like to make a separate Promise.all video.

    • @irobot8297
      @irobot8297 11 หลายเดือนก่อน +1

      dude you seem junior, go back to mdn

  • @pellax
    @pellax 2 ปีที่แล้ว

    Trying to improve my Javascript, great video, subscribed

  • @TarekFaham
    @TarekFaham 2 ปีที่แล้ว

    I needed this in a project coming up soon. Thanks a lot for your help.

  • @dweblinveltz5035
    @dweblinveltz5035 2 ปีที่แล้ว +4

    I love the reduce method. So many different applications for it; having said that, I really hope not to see this usage out in the wild. The first three variations were clearer, easier to read, and more effective. One thing I really don't like is the "magic" that seems to be occurring. When I first glance at it, my first question is, "Why isn't the callback returning something?" I can imagine every new dev being thrown off by how that works.

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      Great comment, Dweblin! 💯

    • @quinndirks5653
      @quinndirks5653 2 ปีที่แล้ว

      Took me a good 5 minutes to figure it out, lol. I can definitely see how it would take a newbie much longer. It should be called "previousPromise" instead of "accumulator"... once you figure out the reason that is, then you must understand it. "async" functions return promises, even if the async function body returns undefined, either explicitiy or implicity, it will implicitly return a promise, but it will resolve to undefined, or whatever the value was that was returned by the async function body. So, in the context of the reduce method example, that means the accumulator, or "previousPromise", is always a promise that resolves to undefined, since, one, the callback was "async", meaning it returns a promise, and two, the callback did not return a value, meaning the promise will resolve to undefined. And, although the iterations are executed instantly for every id within the reduce method, which could result in asynchronous out-of-order execution when the "getPost" promises resolve at different times, it doesn't since the return value of each iteration is passed into the next iteration, and that return value (which is a promise) is awaited in the next iteration, which effectively lines the calls up and makes them wait for the previous iteration to complete before executing the next iteration. Gah, what a headache to understand. I much prefer the await promise.all solution.

  • @caffeinated-pixels
    @caffeinated-pixels 2 ปีที่แล้ว +3

    Good stuff Dave. It's interesting that when you learn functional programming in JS, you are constantly told that using for loops is bad because it's imperative, but I guess that's not always the case! Anyway, that reduce method is cool.

  • @torinzhou2626
    @torinzhou2626 2 ปีที่แล้ว

    That’s amazing Dave! You’ve made it crystal clear! Thanks for you efforts!👏👏👏👏

    • @torinzhou2626
      @torinzhou2626 2 ปีที่แล้ว

      And I’m heading to your pure function video😀Have a strong feeling I would regret if I miss that one.

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      You're welcome! 💯

  • @samirsamir7779
    @samirsamir7779 2 ปีที่แล้ว +1

    Thank you Dave for this super great dev. Channel as Well as your Teaching way .

  • @rajapboyev3928
    @rajapboyev3928 2 ปีที่แล้ว +1

    Big thanks to Dave Gray, very good explanation😃

  • @johnmcaulay4348
    @johnmcaulay4348 2 ปีที่แล้ว

    Learnt this one the hard way the other day, should have been paying more attention to your videos!

  • @focusiam2027
    @focusiam2027 ปีที่แล้ว

    Road to 500k, congrats for the 100k🎉🎉🎉🎉

  • @kumar-jatin-2000
    @kumar-jatin-2000 ปีที่แล้ว +1

    Thanks Dave. I learned this lesson the hard way. I was using venom-bot and xlsx to automate sending a bunch of whatsapp messages to someone. I tried using forEach and async. That didn't end well lol.

  • @alexanderkomanov4151
    @alexanderkomanov4151 2 ปีที่แล้ว

    I really happy that I found your channel. Your manner of explanation is the one of the best I saw. Thanks a lot for the content! Describe and big like from my side!

  • @jollybeancomedy
    @jollybeancomedy 2 ปีที่แล้ว

    Thank you for the video! The forEach not executing in order thing once got me into trouble, hope I had noticed it earlier.

  • @kevinbatdorf
    @kevinbatdorf 2 ปีที่แล้ว +5

    forEach should always be used when you can (and have side effects). It’s a declarative approach that abstracts the implementation (and optimizations) to the browser.

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว +1

      Yes, forEach creates side effects. I prefer map, filter and other approaches when possible due to this. The video does not say you shouldn't use forEach. It does say it doesn't work the way many expect it to when they combine it with async requests.. and it provides a few alternatives to that approach.

    • @kevinbatdorf
      @kevinbatdorf 2 ปีที่แล้ว +1

      @@DaveGrayTeachesCode At the beginning you heavily imply it shouldn't ever be used. But it should actually be preferred in all cases where you would otherwise use a for loop and have side effects, except the case you demonstrated (async/await). The declarative approach lets the browser optimize the implementation.

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      @@kevinbatdorf the title of the video speaks only to async/await. If it seems I imply forEach should never be used for other uses, it was not intended.

    • @BrianVanderbusch
      @BrianVanderbusch 2 ปีที่แล้ว

      @@DaveGrayTeachesCode just look at the poster frame for this vid... It really strongly implies "don't use for each".

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      @@BrianVanderbusch agreed. It's an attention getter and has generated a few unintended flames.

  • @zoaybk
    @zoaybk 2 ปีที่แล้ว

    map approach was the best one I think, great video thanks

  • @mohamedamineboukraia5528
    @mohamedamineboukraia5528 2 ปีที่แล้ว

    What a great tutorial Dave!!

  • @0xAndy
    @0xAndy 2 ปีที่แล้ว

    Thank you so much. I'm a new subscriber and really enjoy the channel so far.

  • @cleancode2123
    @cleancode2123 2 ปีที่แล้ว +2

    Nice one learned a lot !.

  • @shrooobdude
    @shrooobdude 2 ปีที่แล้ว +1

    I'm a bit late to this video, but Promise.all does retain the order. Think of it as passing an array of promises, when each promise resolves they are transformed into their resolved value, but their position in the array does not change. So while they resolve at different times, the order is retained. I hope this makes sense :)

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      It does make sense. I don't think I said Promise.all wouldn't work? It's been months so I would have to watch it myself 😃

    • @shrooobdude
      @shrooobdude 2 ปีที่แล้ว

      @@DaveGrayTeachesCode oh no you never said Promise.all wouldn't work - just that the order may not be retained 😁

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว +1

      @@shrooobdude ah I see! I'd like to make a separate Promise.all video as well.

  • @dindoleonard
    @dindoleonard 2 ปีที่แล้ว

    So glad i stumbled into this gold mine of a video

  • @timderks5960
    @timderks5960 2 ปีที่แล้ว

    Great video. In the beginning I was very adamant that forEach was a great choice given your examples, since it runs the promises concurrently. I must admit, your other approaches do a better job of making it actually clear that things are running either in serial or concurrently, and clarity is everything in code.
    I did kinda miss an example of how to use a concurrent method with a simple sort to get the same result as a serial process, only much, much faster. I understand that wasn't quite the scope of the video, but somebody who's just getting into this kind of stuff may now be convinced that serial HTTP requests is the only way to get serial data.

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      Thanks, Tim! Yes, the focus here was keeping the request / response in the order expected and how forEach can provide surprising results. If you want to share a Github gist link with a concurrent method that is sorted, that would be a welcome addition!

  • @urssaf343
    @urssaf343 2 ปีที่แล้ว +6

    Let's not forget "for await... of" loops and "generators" solution.

  • @hv7460
    @hv7460 2 ปีที่แล้ว

    Thanks a lot....I was yesterday calling Restendpoint1 inside foreach and Restendpoint2 outside foreach.... and the requirement was that Restendpoint1 should be called before Restendpoint2 ...but could not figure out this weird thing about foreach.... Thanks for sharing this...

  • @TheDaviddoodles
    @TheDaviddoodles 2 ปีที่แล้ว

    Hey Dave would you do some videos about Svelte I really love the way explain things

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      Thank you for the request! It may be awhile, but I'd like to do something with Svelte, too!

  • @subhajitpanja1353
    @subhajitpanja1353 2 ปีที่แล้ว

    Sir, you are the best JS teacher to me.
    Thank you for your efforts in making these videos. When I watch your video concept of that tropic getting clear.
    I have already requested you to make a video on React testing.
    That subject I want to learn from you.

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      Thank you for the kind words and again for the request! 🙏

  • @brightmatter
    @brightmatter 2 ปีที่แล้ว

    Concurrent also has a bigger issue. If you attempt to do too many concurrent operations at once you can begin quasi-blocking other operations because you are clogging the thread with to many requests for work at once. The way to handle this is designing a limited concurrent operation stack/queue. I've made them in the past, but I used callbacks, timers, and recursion. Modern implementations would likely use promises, and I'd love to see how that is done.

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว +1

      In this video, I demonstrate several alternatives that do indeed work by awaiting promises to fulfill. 💯

  • @vitason100
    @vitason100 2 ปีที่แล้ว

    Hi Dave,
    Thank for this tutorial !!!
    Can you explain how we can handle error in this way, thank you.

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      Try / catch blocks are good for handling errors 💯

  • @manujohn5346
    @manujohn5346 2 ปีที่แล้ว

    Wow...very helpful. Wish I had seen this few months back. Would have saved me a ton of time😅

  • @gradar7891
    @gradar7891 2 ปีที่แล้ว

    Most informative tutorial I’ve ever encountered for recent years 😄

  • @janjankowski8701
    @janjankowski8701 2 ปีที่แล้ว

    A small addition to the last serialized example:
    const getPostsSerialized = async (ids) => {
    const result = await ids.reduce(async (acc, id) => {
    const prev = await acc;
    const post = await getPost(id);
    console.log(`post id - ${id}:`, post);
    return [...prev, post];
    }, Promise.resolve([]));
    console.log("result:", result);
    }
    Allows you to receive an array of all returns by the end like promise.All()

  • @john_paul_r
    @john_paul_r 2 ปีที่แล้ว

    Worth noting that Promise.all will maintain the order that you pass the promises to it. The promises can complete in any order, but the returned results will always match the order of the passed array of promises.

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว +1

      Agreed, and noted in some other comment discussions, too. The array holds the order. Thanks! 🙏💯

  • @SkyrimBeast
    @SkyrimBeast 2 ปีที่แล้ว

    Another great video Dave, many thanks. How could we go about fetching data from 2 API endpoints where the second API call depends on JSON data from the first API endpoint? Maybe this could be a future tutorial if you're so inclined.

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      Good question and request! This requires waiting for one response before moving on to the next. I would use async / await and confirm success before moving to the next. In React, we use different states like isLoading, isSuccess, and isError to trigger different page renders.

  • @LordValtrius
    @LordValtrius 2 ปีที่แล้ว

    There's an issue with your reduce method. `await acc` isn't doing anything because you're not returning the promise. It's getting resolved instantly and moving onto the `getPost` which it is awaiting.
    Additionally you shouldn't use await within a loop (I never use it outside of a loop) because you have to wait for it to finish before moving onto the next iteration. Use `then` instead (which gets returned, obviously) so each request is "concurrent" but resolves in order.
    Also James Q Quick's code will also resolve in the correct order everytime as Promise.all returns an array of responses in the order the promises were passed in and would also be concurrent.
    Im replying on my phone but if you want an example of the reduce-then method just give me a shout.

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      Wow, I appreciate the time it took you to give such a detailed response. Thanks! Good discussion items even if we do not agree on all 😀
      If this video wasn't about receiving a serialized response, I'd agree that 'await acc' isn't doing much in the reduce solution... but it very much is. If you remove it, your response results will not be in order (serialized). Maybe I should have said what my comment in the code says which is "waits for the previous item to complete" instead of saying it resolved.. but the concept is clear.
      I'd like to see some references on not using await in preference of .then() in a loop. I believe await is legitimate when used appropriately.
      I do agree on the Promise.all as I have discussed with others in these comments, too. My example does work as shown for Promise.all. However, I said it may not provide serialized results, but it indeed consistently does.

    • @LordValtrius
      @LordValtrius 2 ปีที่แล้ว

      @@DaveGrayTeachesCode Hi. I wasn't sure if you would see my comment, never mind reply to it so thanks for that.
      You're right in that `await acc` is necessary for the loop to wait for the previous iteration. I didn't realise a promise is always returned from an async function even when not explicitly returned, did I mention I don't use async/await 🤣
      I still don't think the waterfall approach is best for ajax requests. Here's my concurrent solution that acts on the data in a serialised way, reduce-ing the overall time taken. It's the best of both worlds from James Q Quick and your serialised approach since it can run on the data available while it waits for the next ajax req to finish.
      codesandbox.io/s/elegant-wiles-tvnqk6?file=/src/index.js

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว +1

      @@LordValtrius I appreciate the reply - and great share! Thank you! 💯🚀

  • @Ginold
    @Ginold 2 ปีที่แล้ว

    i did not understand WHY a forEach loop does not allow for async promise whereas for loop does?

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      I don't know if I can explain it here better than the video, but forEach wasn't really designed for promises. It does not wait on them to fulfill or reject. I show some alternatives in this video that will await the response and allow you to keep the results serialized.

  • @tomascarignano5002
    @tomascarignano5002 2 ปีที่แล้ว

    This is amazing! Thank you for the great explanation

  • @basilistigris640
    @basilistigris640 2 ปีที่แล้ว +1

    one more masterpiece Javascript video lesson, very professional and perfectly explained lessons in javascript, very orginized channel, i learned a lot, thank you Dave Gray!

  • @jiweihe3413
    @jiweihe3413 2 ปีที่แล้ว

    Thanks for the interesting video! I just have a naïve question. 3:10 I thought hoisting does not work for arrow functions, but it works for the useforEach() arrow function. Just curious why.

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว +1

      That's a great question! I must have the initApp function defined before the event listener that calls it, but because I'm calling initApp with an event listener, it allows me to define everything else below. If I just called initApp() without the listener, this would not work. The DOMContentLoaded event has to fire before initApp is called. A similar explanation on StackOverflow: stackoverflow.com/questions/72235699/how-does-function-within-addeventlistener-gets-hoisted

    • @jiweihe3413
      @jiweihe3413 2 ปีที่แล้ว

      @@DaveGrayTeachesCode I see. That makes sense! Thank you so much!

  • @DM-pg4iv
    @DM-pg4iv 2 ปีที่แล้ว

    This is pretty cool. So is forEach just nlt a good idea ib general? Let's just say a regular func that you want to go through data. Is for of better?

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      Nothing wrong with using forEach for many needs, but if you desire a serialized response to requests, it is not the one to choose.

  • @arminmatthes
    @arminmatthes 2 ปีที่แล้ว

    What I don't like about the reduce example is that you can't really return the resulting values as an array because you've put the promise into the accumulator... You don't always just want to log the result in the callback.
    You could pass in an object {lastPromise: null, result: []} and then adapt your code accordingly - if lastPromise is null, just dispatch the first Promise, then skip ahead to the next call. After awaiting the promise, push the result onto acc.result.
    Voila - you can have the cake and eat it, too.
    I just made this up without actually testing it, but it should work.

  • @repenning1
    @repenning1 ปีที่แล้ว

    not sure why you would advocate using reduce over for_of. The main point of reduce is to bubble some computation such as a number accumulator not to just to chain promises. Of course you can serialize this kind of operation using reduce but this is unnecessarily complex because you are not reducing return values from async function but only promises. Makes more sense to let the for_of do this.

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  ปีที่แล้ว

      It's been awhile but I don't think I did advocate for anything over for_of. I think I showed several examples to use instead of for_each. I don't think I declared one example was above the others.

  • @cas818028
    @cas818028 2 ปีที่แล้ว +2

    Devs care about other devs and their mental health. Please don’t ever use reduce this way. Thank you

  • @arshiagholami7611
    @arshiagholami7611 2 ปีที่แล้ว

    I really liked the idea of using reduce here, never seen something like this. thanks for the great vid

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      It is an interesting use. Thanks for the comment! 💯

  • @laurentgauthier8742
    @laurentgauthier8742 2 ปีที่แล้ว

    Super interesting! Thank you so much!

  • @atgaming263
    @atgaming263 2 ปีที่แล้ว

    This forEach problem was only in JS or in all programming language that has forEach function ?

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      I cannot speak to all programming languages, but in JS when you need to have serialized requests & responses, this provides some alternatives.

  • @PauloSantosk
    @PauloSantosk 2 ปีที่แล้ว +7

    forEach respected the await instrucion, but It was executed recursively in a more performatic way.
    If you need order, sort the results.

    • @fParad0x_
      @fParad0x_ 2 ปีที่แล้ว

      Do you have any info on how that works? I didn't know that forEach was executed in a different, special way.

    • @PauloSantosk
      @PauloSantosk 2 ปีที่แล้ว +2

      ​@@fParad0x_ it is part of the functional way of solve problems. It is executed utilizing recursion instead of a imperative instruction like the tradicional "for", for example. If you are executing asynchronous calls over a recursion loop, you cant wait the outcome in a ordered way and, "await" will not help too, because each call is in a diferent bubble of the stack and "await" will only wait in the same "bubble".
      But, you should use forEach every possible time, this video is misliding the importance of a functional way of solving the problems.

    • @BrianVanderbusch
      @BrianVanderbusch 2 ปีที่แล้ว

      Exactly.
      "It doesn't return them in order" means it returned them in the order they resolved, and that's what asynchronous is really about.

    • @fParad0x_
      @fParad0x_ 2 ปีที่แล้ว

      @@PauloSantosk Thanks for the explanation! Didn't know that.

    • @n1xx1
      @n1xx1 2 ปีที่แล้ว +3

      This is straight up wrong information. forEach is iterative and not recursive, as you expect for something called "for each", however it's a synchronous function, it doesn't handle anything asynchronous inside. If the function you pass to forEach returns a Promise (that is what a async function is), it doesn't wait for it. It's not about being performant or faster, it just isn't what it's meant to do.
      Also it's not about sorting the result. If you do something like:
      const data = [];
      ids.forEach(async (id) => { const res = await getPost(id); data.push(res); });
      console.log(data);
      Most probably data will be empty, because you didn't wait for any of the Promises to resolve. You probably want to go either the "reduce" or the "Promise.all with map" way, or just use a standard for loop.
      I would also like to point out that a for-of loop with awaits inside will execute the functions sequentially, waiting for the previous one to complete before starting the next one, while a
      const data = await Promise.all(ids.map(id => getPost(id));
      Will execute them all at the same time, and return when all are completed. So they are not alternatives to each other, really.

  • @wojciechjarosz420
    @wojciechjarosz420 10 หลายเดือนก่อน

    ...and how to return fetched and resolved data from reduce function in this case?

  • @polinafeterman5057
    @polinafeterman5057 2 ปีที่แล้ว

    Thank you for this explanation. Very clear and useful! Could you please tell me what is this extension that you called Dev Tools For Chrome? I can't find it in VS Code... Thank you!

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      It is built into Chrome already. No extension needed. Right click your web page and choose "Inspect" from the menu to open dev tools. Or press Ctrl+Shift+I to open.

  • @randomnobody660
    @randomnobody660 2 ปีที่แล้ว

    I'm not sure I see the issue? For each element in the array you asynchronously did some stuff to it (in this case called some api then logged the result), so of course each operation doesn't, and imo shouldn't, wait for the previous one to finish no? In fact why are we awaiting each fetch in the for loop anyways?
    I don't even understand what's in the video's opinion the better alternative; imo it would be more counter intuitive and less useful if you couldn't do async operations with foreach loops. Is the point just that foreach is a special case of map? I mean sure, but they express different intent (to the programmer/reader), which imo is important. Most branching statements are just conditional gotos with maybe some stack pushing and poping, yet people still somewhat pick and choose for this reason.
    I think it's quite expressive that you use reduce if you want each item to depend on the last, map if each item is independent, and foreach if the prior is true but you also don't care about return values.
    I'm sure there are legitimate gripes with foreach, but I didn't personally find this particular one convincing.
    Also also, if you really want it to "return" something you could always assign the promise somewhere then await outside no?

    • @randomnobody660
      @randomnobody660 2 ปีที่แล้ว

      ok, so those are all talked about in the video as alternatives but again, what's the advantage of switching? Still not sure I understand.

    • @randomnobody660
      @randomnobody660 2 ปีที่แล้ว

      plz no delete again...but foreach can also return like so:
      ```
      const getPost = async id => (await fetch(funnyURL+ id)).json(); // i suspect the url is why youtube keeps deleting this
      const getPostsForEach = async ids => {
      let ret = [];
      ids.forEach((id, i) => ret[i] = getPost(id).then(console.log));
      await Promise.all(ret);
      console.log('i\'m waiting fine?');
      }
      ```
      Also, like another gent mentioned, no need to async if you aren't awaiting. Also also, no need to await right before a return.
      In the case of getPost, the caller is going to get a promise if the caller doesn't await, or the promise if it does, whether you add that 2nd await or not.

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      Thanks for all the input. Yes, all alternatives listed. Far too often I see beginners use forEach while awaiting promises and expect to get the results back in the order of the requests. The video points out that is not going to happen. For serialized results, the alternatives I've provided - and others have added in the comments - are better choices. The thumbnail for the video has brought out some stronger opinions, and at the same time garnered a few more views.

  • @Shubhaw
    @Shubhaw 2 ปีที่แล้ว

    This is the exact same problem I faced last week in my office. Thanks for the solution. Although I would like to know why "await" doesn't work inside the forEach method body. Any links where I can read it in more depth?

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว +2

      You're welcome. Yes, go down to the 2nd blue block on this page where it says "Note: forEach expects a synchronous function." developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

    • @Shubhaw
      @Shubhaw 2 ปีที่แล้ว

      @@DaveGrayTeachesCode Thanks again! :)

  • @luisaugsburger
    @luisaugsburger 2 ปีที่แล้ว

    Thanks dude! nice explanation!

  • @oksanakobyliatska6822
    @oksanakobyliatska6822 2 ปีที่แล้ว

    Thanks a lot, that was very helpful!

  • @TheRishikesh99
    @TheRishikesh99 2 ปีที่แล้ว +1

    the async foreach is weird because i would not expecting ordering in code that runs ASYNChronously. If you want ordering, you need to maintain it either with promise.all and map. Foreach is nice to have when you want async side-effects

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      Agreed 💯 There is an example of using Promise.all in this video along with a few other possibilities.

  • @TarekFaham
    @TarekFaham 2 ปีที่แล้ว

    Do have tutorials about design patters in JavaScript? I'm looking for one to learn how to avoid using if then else statement using polymorphism. Can you help with this please?

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว +1

      I do not at this time, but it is a good idea! Thanks for your request!

  • @ScriptRaccoon
    @ScriptRaccoon 2 ปีที่แล้ว +4

    I really like the concurrent version since it is faster. When we care about the order of posts, we could just sort them after we have fetched them, right? I am not sure though if this is still faster than the serialized version then, it probably depends on the number of posts we fetch.

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      Nailed it here. It's going to depend on the number fetched and if you are adding the results to specific serialized data after receiving it. Several considerations. 💯

  • @kevinbatdorf
    @kevinbatdorf 2 ปีที่แล้ว +1

    Never leave side effects in your reduce function. It should be a pure function that returns the accumulator. That console.log should be removed if anyone is using code from this video.

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      Yes, I do hope everyone understands to not leave console.log in any released code as you might see in a tutorial. You've got a long day ahead if you leave this note on any video using a console.log. Have a good day, Kevin!

    • @kevinbatdorf
      @kevinbatdorf 2 ปีที่แล้ว

      @@DaveGrayTeachesCode That's fair. I felt the tutorial was well made otherwise so I wanted to point out a couple things that might affect new coders. Wasn't a dig on you personally.

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      @@kevinbatdorf all good my friend. I didn't think it was, but I agree console.log should be removed from any examples used from a tutorial.

  • @tyler8995
    @tyler8995 ปีที่แล้ว

    What's the extension that gives that line between your opening and closing braces?

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  ปีที่แล้ว +1

      Here you go: th-cam.com/users/shortsMDaxWffMjrQ

    • @tyler8995
      @tyler8995 ปีที่แล้ว

      @@DaveGrayTeachesCode thank you!

  • @navazsharif6783
    @navazsharif6783 2 ปีที่แล้ว

    Just came here after watching James Q Quick video that you are talking about at 11:00

  • @krishanlanka7659
    @krishanlanka7659 2 ปีที่แล้ว +1

    hi, can you correct my php if statement pls

  • @Jay-dq5mq
    @Jay-dq5mq 2 ปีที่แล้ว

    why not consider using bluebird.map() instead?

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว +1

      I provided some alternatives in the video, but not all alternatives. If used correctly, map() will work. So will reduce(), flatMap(), and reduceRight().

  • @sheelaveldurai2900
    @sheelaveldurai2900 ปีที่แล้ว

    how to break/exit the reduce loop and return the last value?

  • @MichaelMcGreal
    @MichaelMcGreal ปีที่แล้ว

    Nice use of reduce!

  • @rike7777
    @rike7777 2 ปีที่แล้ว +1

    Very enlightening lesson. I really liked to see the difference between the serialized and the concurrent versions, as well as the use of reduce to solve the problem, although it is difficult to grasp at first. By the way, I also liked you VS Code Theme, which is easy on the eyes. Can you please tell me what it is? Thank you!

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว +1

      Glad you found it helpful. And yes, I just switched to this theme and really like it. It's the Github Theme. Several dark modes to choose from.

  • @decay6591
    @decay6591 2 ปีที่แล้ว

    fixed redux thunk bug. appreciate. got sub

  • @luiizmorales316
    @luiizmorales316 2 ปีที่แล้ว

    thanks bro... good video 👍🏽

  • @ericapinheiro9891
    @ericapinheiro9891 2 ปีที่แล้ว

    Amazing reducing js!

  • @thecutedreamkostasp.4449
    @thecutedreamkostasp.4449 2 ปีที่แล้ว

    Thx God there are better programmers than me. They make me bettter. I appreciate this sir.

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      I'd suggest avoiding thoughts about who is better or not. I always say keep striving for progress. A little bit every day is the goal. 💯

  • @코린이31세
    @코린이31세 2 ปีที่แล้ว

    Amazing lecture!!!! Thank you sir 👍👍

  • @arminmatthes
    @arminmatthes 2 ปีที่แล้ว

    I agree that it's important to know this beforehand, but it behaves exactly the way I'd think it should behave. To say that this should never be used in modern JavaScript is a bit dramatic. I use it all the time and I know what to expect. Oftentimes I don't need the data to be fetched in correct order.
    Besides, I think the bigger problem is that it can be hard to actually wait for all promises to resolve using forEach.

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว +1

      I think this video has been misunderstood a little based on the thumbnail without some seeing it specifically addresses async / await code and serialized results. There is nothing wrong with using forEach, but many expect different results when combining forEach with async/await. This video provides those looking for a solution with alternatives that give the functionality they expected to get when using forEach.

  • @designcoded7585
    @designcoded7585 2 ปีที่แล้ว

    most of the frameworks and peoples are using .map() only both for iteration like for loop os even for returing from the helper function , so far map is the popular way , so there no suprise , but for just practising we can use forEach() its nice

  • @nemanjasavic9859
    @nemanjasavic9859 6 วันที่ผ่านมา

    Ooooooooo my god... I lost 2-3 hours because of this... I am lucky, you saved my ass.. A was using foreach.. Thank you so much

  • @mohamedabdelkefi9947
    @mohamedabdelkefi9947 2 ปีที่แล้ว

    thank you you saved my day

  • @melpacheco9288
    @melpacheco9288 ปีที่แล้ว

    Masterful!

  • @TheYinyangman
    @TheYinyangman 2 ปีที่แล้ว

    Why do the higher order array methods not always return serialised data ?

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      Specifically, this applies to responses you await with async code. Some of the higher order methods are not designed to await responses. For example, forEach has no return. The response is not guaranteed to come back in the order the request was sent either. Some of the alternatives presented here help keep the responses received in order.

  • @show_me_the_moneyy
    @show_me_the_moneyy ปีที่แล้ว

    Good one - reduce was a mind bender - I wonder if reduce is preferable for something like this because readability is impacted

  • @debjyotibanerjee9846
    @debjyotibanerjee9846 2 ปีที่แล้ว

    Wonderful video..

  • @aman7555
    @aman7555 2 ปีที่แล้ว

    Awesome 👌

  • @saitejagatadi9711
    @saitejagatadi9711 2 ปีที่แล้ว

    13:13
    Dave, The mobile mode was on in browser. Not sure it was intentional 😄

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว +1

      I usually have mobile mode on when I open Chrome Devtools.

  • @VirtualDarKness
    @VirtualDarKness 2 ปีที่แล้ว

    In the reduce, isn't the accumulator always the initial value without a return?

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว +2

      Been awhile since I looked at this tutorial, but I remember another discussion in the comments along these lines. Reference here, too: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

    • @VirtualDarKness
      @VirtualDarKness 2 ปีที่แล้ว

      @@DaveGrayTeachesCode thanks! And very interesting video

    • @VirtualDarKness
      @VirtualDarKness 2 ปีที่แล้ว

      @@DaveGrayTeachesCode ok I understood what I was missing... Because the function is async it does of course return a promise, not undefined 😅

  • @djkos7
    @djkos7 2 ปีที่แล้ว +1

    Dave, seriously, you need to get known what is async callback, why sync iterator does not care about it, how promises will be resolved in the callback Q, and for sure regarding functions context, and closures.
    From other side, forEach was made with only 1 aim - apply callback function in sync way for each element in the array. That’s all, no other magic there

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      I'm not sure if you are saying I "need to get known" or you are saying I "need to learn about" what you are listing.. but my friend, I think we are talking about the same things.

  • @autobot021
    @autobot021 2 ปีที่แล้ว

    the promise.all method does not seem to work for me

  • @johnmcaulay4348
    @johnmcaulay4348 2 ปีที่แล้ว +2

    Hey Dave!
    Quick question about this. I have a situation where I need to loop through asynchronous calls to an API and the next API call depends on the value of a property from the previous API call in the loop.
    Is my best bet here just a regular for loop with awaits? That's how I currently have it working, but it seems a little dirty.

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      Good question, John and that's the focus of this tutorial. I think the solution provided here that is easiest for all to understand is the for...of loop. The reduce solution also works as shown, but it may be a little more difficult for everyone to understand. Either will work! 💯

    • @johnmcaulay4348
      @johnmcaulay4348 2 ปีที่แล้ว

      @@DaveGrayTeachesCode yeah I need to go back through the reduce solution, it went over my head a little. I'm constantly surprised by the possibilities of reduce. Thanks for the reply!

  • @CesarScur
    @CesarScur 2 ปีที่แล้ว

    The "problem" is not with the foreach concept. It is with the closure implementation of this foreach. Foreach is not evil.

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว

      Never said it was. This video is for those who try to use forEach when they want a serialized response.

  • @marufnajm7453
    @marufnajm7453 2 ปีที่แล้ว

    Very interesting

  • @dheerajs2838
    @dheerajs2838 2 ปีที่แล้ว

    this was agreat tutorial .. impressive

  • @AK-vx4dy
    @AK-vx4dy 2 ปีที่แล้ว

    Sorry to say but initial example is bad or badly explained
    forEach executes in order, but every call lives it's own live and results come randomly from api call,
    it's not bad it is how it works (but maybe it is hard to understand)
    forEach don't wait because its job is iterate over elements not wait to execute all calls.

    • @DaveGrayTeachesCode
      @DaveGrayTeachesCode  2 ปีที่แล้ว +1

      You're saying the same thing I demonstrated. I don't expect everyone to like my explanations, no worries.

  • @FullStackDevGreg
    @FullStackDevGreg ปีที่แล้ว

    Thankyou very much sure

  • @Dibakash
    @Dibakash 2 ปีที่แล้ว

    Amazing.

  • @kirindev
    @kirindev ปีที่แล้ว

    thank you.