Managing Promise Concurrency in JavaScript

Поділитися
Вставка
  • Опубліковано 28 лис 2024

КОМЕНТАРІ • 54

  • @adiadiadi
    @adiadiadi 9 місяців тому +19

    Selfishly, I prefer when you cover intermediate/advanced/niche topics like these as there's already a deluge of beginner-level content. But I get that beginner content can draw more views which would yield a higher return on the effort you put it. I don't mind the occasional TypeScript video either. Honestly man, you do you. I find your videos to be a cut above the rest generally.

  • @senshiougonno7017
    @senshiougonno7017 9 місяців тому +9

    to answer your question
    YES
    demo-ing how to resolve some of the problems that you or people you know might have encountered is probably very helpful for a lot of us out there
    Keep it up !

  • @KubaBogaczewicz
    @KubaBogaczewicz 9 місяців тому +20

    Very nice video, but you have a race condition. Look at that code:
    let a = [];
    a[2] = "hello";
    console.log(a.length); // === 3
    Your overall mapPromises does not resolve when all promises resolve, it resolves when the last promise resolves (function next, line 20).

    • @andrew-burgess
      @andrew-burgess  9 місяців тому +3

      ooooh, that's a really good catch! I guess the simplest way to solve it is with `let completed = 0`, increment in the final `then`, and check that `completed === args.length`. Thanks!

    • @fardolieri
      @fardolieri 9 місяців тому +2

      Another quick fix could be to check for `Object.keys(results).length` instead of `results.length`. But the `let completed = 0` approach is probably is more readable.

    • @andrew-burgess
      @andrew-burgess  9 місяців тому +1

      yeah that works too. I don't love the extra unnecessary iteration of results, though.

  • @MichiganTypeScript
    @MichiganTypeScript 9 місяців тому +5

    this is a really cool concept! glad to have watched to the end because the whole time it seemed like there _must_ already bee some API for this, but yours is unique. It's pretty neat how you managed to do it so succinctly, too!

    • @mazwrld
      @mazwrld 9 місяців тому

      i agree

  • @capability-snob
    @capability-snob 9 місяців тому +1

    Your .then() is always run on an almost empty stack - this is part of the A+ spec and reflects the original semantics in E. The only thing there is a resolver, but the promise itself is unused, so it's not that different to explicitly using setImmediate afaict.

  • @Jelle-DV
    @Jelle-DV 9 місяців тому

    Awesome! Maybe you could start the video with a quick demonstration of how your end solution can be used/called, and then start building it

  • @shivankmittal2226
    @shivankmittal2226 9 місяців тому +1

    This is exactly what kind of videos i am looking for. Getting to know how we can use them properly

  • @fardolieri
    @fardolieri 9 місяців тому +2

    setTimeout is a drop-in replacement for setImmediate and has browser support. If not given a delay parameter it behaves as if passed a 0, so just like setImmediate.
    But in your case I think it would be fine dropping it altogether. I can't see the drawback of simply using `.then(next)`. They are not really bound to each other because your next function never returns anything.

  • @Haawkyy
    @Haawkyy 9 місяців тому

    Awesome! Nice feature to work on; executed quickly and with clear explanations. Thanks a lot for this one (and yes, please, continue on this path).

  • @rendezone
    @rendezone 9 місяців тому

    It’s better to use finally than then in case catch throws, but in your case then will work. I think finally has better semantics for what you want to convey

  •  9 місяців тому

    TypeScript and JavaScript videos are awesome!! Please go ahead with both types!!

  • @lenaggar
    @lenaggar 7 місяців тому

    first of all YES!
    second, I have a comment on the implementation, there's a possibility (in the case that the concurrency limit is 3) that either one of or both of the 2 jobs before the last one finish after the last one does; in this case the returned results list will have their corresponding values in the results array as undefined, and also callback will be called more than one time. possible solutions I could think of:
    1- do a filter operation on existence of values before checking for equality with the inputs array length; else if (results.filter(Boolean).length == inputs.length)
    2- use a Map keys as the index of the result in the array and values as the result; verify using map.size rather than results.length; then when you finally resolve, you can map it into an array again

    • @lenaggar
      @lenaggar 7 місяців тому

      Oh! I just watched your next video, your solution using the `settled` counter is much simpler. Thank you for that one

  • @lacherolachero9409
    @lacherolachero9409 9 місяців тому

    Absolutely more of this advanced stuff!

  • @fagnersales532
    @fagnersales532 9 місяців тому

    I actually loved it, I'd appreciate to see it again but typescript is also fun as well.

  • @Shr11mp
    @Shr11mp 9 місяців тому

    Yes, this was an awesome video! I'd love to see more of this.

  • @SaurabhChopra-m5p
    @SaurabhChopra-m5p 9 місяців тому

    Love your videos, there is always something to learn from you. Keep doing it

  • @raflidewanto
    @raflidewanto 9 місяців тому

    Would love to see more of this👍

  • @dimitro.cardellini
    @dimitro.cardellini 9 місяців тому +1

    Pretty nice.
    Small comment. The function is not universal and difficult to describe types for it.
    Here is the typed one:
    type Task = () => Promise;
    type TaskResult = T extends Task ? R : never;
    const concurrentAllSettled =
    (concurrency: number, ...tasks: T): Promise => new Promise((resolve) => {
    const count = tasks.length;
    const results = Array(count).fill(undefined) as { // PACKED_OBJECTS
    [K in keyof T]: PromiseSettledResult
    };
    let current = 0;
    let settled = 0;
    const next = () => {
    if (settled === count) { resolve(results); return ; }
    const index = current++;
    const task = tasks[index];
    task()
    .then(
    (value) => { results[index] = { status: "fulfilled", value }; },
    (reason) => { results[index] = { status: "rejected", reason }; },
    ).then(
    () => { settled += 1; next(); },
    );
    };
    while (concurrency-- > 0) next();
    });

  • @cesardiaz1925
    @cesardiaz1925 9 місяців тому

    Use of setImmediate was beautiful. Introduced me it so thanks

  • @reverser41
    @reverser41 9 місяців тому

    love any kind of videos that you make.

  • @rockNbrain
    @rockNbrain 9 місяців тому +1

    Nice job dude 🎉

  • @sidwebworks9871
    @sidwebworks9871 9 місяців тому

    setImmediate unlike the name won’t run “as soon as possible” instead it will enqueue the task at the end of the current loop iteration.
    If you need something to execute in the same tick or “as soon as possible” use process.nextTick instead
    The naming is messed up IK but its just a little node gotcha

  • @PaulSebastianM
    @PaulSebastianM 9 місяців тому +1

    You're not implementing the concurrency flag like you said you would. It's acting more like a count of promises to start, and not an an amount of promises to schedule at a time... correct me if I understood incorrectly.

  • @nazarshvets7501
    @nazarshvets7501 9 місяців тому +1

    I`m really curious about that call stack situation. How is that even a thing? Actually have no clue how call-stack(s?) works

  • @evandroLG2
    @evandroLG2 9 місяців тому

    Cool video! Thanks!
    Just out of curiosity: I solved this same problem during a coding interview at Uber, in 2021.

    • @lenaggar
      @lenaggar 7 місяців тому

      that's funny; I interviewed at Uber last year and got the same problem during my interview but it was using callbacks instead of promises

  • @edgeeffect
    @edgeeffect 5 місяців тому

    As long as it's intermediate or advanced level... I like a nice mixture of TypeScript and JavaScript.

  • @tthiagolino8
    @tthiagolino8 9 місяців тому

    Love both kinds of videos

  • @AlImam-o9k
    @AlImam-o9k 9 місяців тому

    this kind of video is really cool

  • @PickleRiiiiiiick
    @PickleRiiiiiiick 9 місяців тому

    Both types of videos are good. Mix it up!

  • @connornusser-mclemore631
    @connornusser-mclemore631 2 місяці тому

    What font is that I love it?

  • @danel1922
    @danel1922 9 місяців тому

    atm i'm doing only django/oscar work, man i miss js. to answer your question: yes, more please!

  • @malvoliosf
    @malvoliosf 7 місяців тому

    There is a huge bug in your code!
    The results are returned in the order they were resolved, NOT the order they appeared in the original args array. Make a function that has the functionality “given n, wait 10-n seconds then return n” and run it with an array 0 through 9 and a concurrency of 10. The numbers will be returned in reverse order.

  • @UserUnknown6
    @UserUnknown6 9 місяців тому

    Won't wrapping the contents of the mapPromises function in a promise do the same as using this new, experimental feature? Or am i missing something?

  • @Matt23488
    @Matt23488 9 місяців тому

    You seem to be pretty good about making videos on interesting topics, TypeScript or not. So in my opinion just keep doing what you're doing, if you find something you think is worth making a video about, it probably is.

  • @awekeningbro1207
    @awekeningbro1207 9 місяців тому

    what font are you using in the IDE?

  • @dasten123
    @dasten123 9 місяців тому

    I'm in for both kinds of videos, or different ones too :)

  • @hut_fire1490
    @hut_fire1490 9 місяців тому

    Hi andrew love your videos ! Btw can you make a video about map in javascript such when we should use it instead of plain object. Ty ❤

  • @proesus7446
    @proesus7446 9 місяців тому

    does the index start at 1 since cursor is incremented?

  • @mazwrld
    @mazwrld 9 місяців тому

    what’s that font??

  • @mrlectus
    @mrlectus 9 місяців тому

    Can generators be used here?

  • @AliKorkmaz-v3g
    @AliKorkmaz-v3g 9 місяців тому

    what about both Andrew 😄

  • @studiowebselect
    @studiowebselect 9 місяців тому

    P-map for node20 ;)

  • @inuoshios
    @inuoshios 9 місяців тому

    what is the name of your font?

  • @yunyang6267
    @yunyang6267 9 місяців тому

    you look like the guy from Planetscale teaching database so much, it's confusing

    • @daleryanaldover6545
      @daleryanaldover6545 9 місяців тому

      it also doesn't help that they both have square glasses 😂

  • @eljay3762
    @eljay3762 9 місяців тому

    Both .catch(onRejected) [aka .then(undefined, onRejected)] and .finally(onFinally) [aka .then(onFinally, onFinally)] are simple aliases of .then(onFulfilled, onRejected).
    So with that in mind, your code would be better structured as .then(onFulfilled, onRejected).then(onFinally) rather than the current .then(onFulfilled).catch(onRejected).finally(onFinally).
    I would highly recommend reading the MDN docs on .then(), you should find them informative.