How not to use reduce function

How not to use reduce function

How not to use reduce function

Share on

Creating supply chain solutions for a big client is a challenging task for any team. When we first started working on the Mobile Manifest app, it was already being developed by another team. After some initial collaboration, the client decided to transfer the entire development process to us.

While the app was getting bigger, and we were implementing newer features, we started to overlook certain parts of the app. A synchronization process made 10 parallel GET requests to fetch around 8MB of JSON data per request. This sync process allowed users to use the app offline, even in areas with low or no connectivity, like farms in remote fields. However, this process took around 4 minutes on slower devices and 1 minute on faster ones. We accepted this performance for nearly a year without giving it much thought.

Our look into the code

We were always puzzled by why these requests took so long in the app when the same requests sent from Postman finished in just a few seconds. Finally, we found some time between developing new features and fixing bugs to take a closer look at the sync process. One part of the code didn’t make sense to us.

export function toMap(arr: [object], key: string) {
  return arr.reduce((acc: { [k: string]: object }, next: any) => {
const k = next[key];
    return { [k]: next, ...acc };
  }, {});
}

The code above converts a list of objects into a map using a given property of each object as the key.

Here is the example:

const list = [{id: 213, name: "John"}, {id: 455, name: "Jane"}];
const map = toMap(list, 'id');
/* map 
{
       213: {
             id: 213,
             name: "John"
       },
       455: {
             id: 455,
             name: "Jane"
       }
}

When you are dealing with frequent requests to get an object from a list of 10k objects, using the find method on an array will result in O(n) complexity. However, fetching that same object from a map by key can result in O(1) complexity. This is because instead of doing list.find(item => item.id === id), you can simply use map[id]

But what’s the issue with toMap function? If you look closely at the reduce part of the code, you will see that it is not being used correctly. Instead of adding new key-value pair to the accumulator and returning it, the function is creating a new accumulator object on each iteration and spreading the old accumulator into it (while also adding a key-value pair). This is not a problem when working with a list of only 2 elements, but it can cause issues when dealing with a list of 10k elements. And when this process is repeated for 10 parallel requests, the problems become even more pronounced. You can try it out yourself here with a list of 10k simple elements.

Here is an improved toMap function:

export function toMap(arr: [object], key: string) {
  return
arr.reduce((acc: { [k: string]: object }, next: any) => {    
const
k = next[key];
   
acc[k] = next;
    return
acc;
  }, {});
}

Conclusion

A small change in the code can make a big difference in performance. In our case, the sync request on older devices went from 4 minutes to 20 seconds. Here are three lessons we learned from this experience:

Understand the tools you are using

In this case, it is important to have a good understanding of the functions you are using in your code. This will allow you to use them efficiently and avoid common mistakes.

Take time to get to know the project

When you start working on a new project, it is important to spend some time getting familiar with the codebase. This doesn’t have to be done all at once, but setting aside 30 minutes each day to explore the code can be helpful. By doing this, you will gain a better understanding of the project and be better equipped to tackle any challenges that come up.

Don’t just copy and paste code from the internet

It can be tempting to find a solution to a problem online that works and just copy and paste it into your code. However, it is important to understand the code before using it. Take the time to read through it, see if you can improve it, and only then consider adding it to your project. By doing this, you can avoid introducing unnecessary or potentially harmful code into your project.

    More from our updates:

    Our Work

    Explore our recent work

    Services

    Explore what we offer

    info@deegloo.com | Zadarska 80, 
1000 Zagreb, Croatia

    © Deegloo. All rights reserved 2022.