DEV Community

Cover image for js-coroutines gives your code: data indexing and lookup functionality, in idle time

js-coroutines gives your code: data indexing and lookup functionality, in idle time

Mike Talbot ⭐ on July 05, 2020

Following user feedback I've added some key "lodash" like functions to the out of the box features of js-coroutines. I've added keyByAsync group...
Collapse
 
vldmrgnn profile image
Vlad

Great collection! Thanks!

mean time, for the "keyBy" I played around with this.


const myKeyBy = (arr, key) => reduce(arr, yielding((a, c) => (c?.[key]) ? {...a, [c[key]] : c } : {...a} ,{}));
Collapse
 
miketalbot profile image
Mike Talbot ⭐

That should certainly work! I'd just say inside this one function I'd avoid immutability - because nothing has access to the mutable object and it will allocate a lot less memory if you modify one thing rather than make a new one on each loop.

Collapse
 
vldmrgnn profile image
Vlad • Edited

Certainly, and perhaps is significant on large data..
I put up something like this..:

  function* xKeyBy(collection, fn) {
    let result = {}
    yield* forEach(collection, function* (value, key) {
       let newKey = fn(value);
       yield;
       result[newKey] = value;
       yield;
    })
    return result;
  }

  //not blocking UI
  const dispatchKeyBy = async (dt, key, action)=>{

    let kby  = await run(function* () {
            return yield* xKeyBy(dt, x=>x[key]);
     });

    dispatch({type: action.type , payload: kby});

  }

and call it from useEffect from inside a hook...

For some reason I could not use the keyBy provided "out of the box". I think is a npm issue on my side

Thread Thread
 
miketalbot profile image
Mike Talbot ⭐ • Edited

Odd on the "out of the box" all my tests seem to be ok. You probably don't want to yield that much. I'd be saying (if collection is an array) that you should yield every 32 or something using

    if((key & 31) === 0) yield

It's a balance between checking often enough and slowing it down a lot by checking too much.

In more recent versions you can also just call run() on the result of executing the generator, in your example this simplified the second routine to be:

const dispatchKeyBy = async (dt, key, action)=>{

    let kby  = await run(xKeyBy(dt, x=>x[key]));

    dispatch({type: action.type , payload: kby});

  }

npm version should be 2.3.62

Thread Thread
 
vldmrgnn profile image
Vlad

It totally make sense!
Updated the npm as I was way behind... odd that I had to uninstall and then install again. Otherwise it was still version 1.1.36.
I hope that will not break the code now :)
Thanks for everything!

Thread Thread
 
miketalbot profile image
Mike Talbot ⭐ • Edited

Right I added a breaking change a while ago, but it only affects a very small use case, so hopefully all ok. It was when I changed from using an external polyfill for requestIdleCallback to the new internal one.

Thread Thread
 
vldmrgnn profile image
Vlad

Updated an everything seems to work like a charm!
Still It seems that you forgot some "debugger" at keyBy in array-utilities.js.
(Should I have written on GitHub on that? if so sorry)

Thread Thread
 
miketalbot profile image
Mike Talbot ⭐

Ouch lol. Ooops. Fixing that.

Thread Thread
 
miketalbot profile image
Mike Talbot ⭐

2.3.63 - removed the debugger

Collapse
 
prognovel profile image
ProgNovel

Is there any performance benefit using parseAsync(response.text()) than the usual response.json()?

Collapse
 
siimsoni profile image
Kristjan Siimson

This is really situational, because JSON.parse is really fast. With small workloads you will measure it in tens of microseconds. But it does block the event loop.

Collapse
 
miketalbot profile image
Mike Talbot ⭐

Agreed, parse is a lot faster than storage, but definitely can take more than 16.7ms with significant packets. You'd be trading performance for a smooth out, sometimes worth it with large packets. Should only be used if there is a glitch present I'd say.

Thread Thread
 
siimsoni profile image
Kristjan Siimson

If it was an option, I'd also consider using ndjson to split up the JSON objects into manageable chunks to get the best of both worlds.

Collapse
 
miketalbot profile image
Mike Talbot ⭐ • Edited

Yes, even though response.json() looks like it's async, it isn't. So parsing JSON is a lot faster than stringifying it, but if it was huge then this would help. Part of the reason for writing js-c was that I needed an async json.