diceline-chartmagnifierquestion-marktwitter-whiteTwitter_Logo_Blue

Today I Learned

How to optimize the performance of the map function in JavaScript

To optimize the performance of a map function in JavaScript, you can do a few things:

  1. Use the forEach method instead of map if you are not creating a new array from the iteration. forEach is faster because it does not create a new array.

  2. Use the map method on a smaller array if possible. For example, if you have a large array and you only need to map over a subset of it, create a new array with just the subset and use map on that.

  3. If you are using map to transform each element of the array, use a specialized method for the transformation instead of using map. For example, if you are transforming each element to a string, use the toString method instead of using map.

  4. If you are using map to filter an array, use the filter method instead. filter is optimized for filtering and will be faster than using map for that purpose.

  5. Use a for loop instead of map if you need to perform complex operations on each element of the array. map is optimized for simple transformations, so a for loop will be faster for more complex operations.

Alternative method to redirect unauthenticated users with meteor.js and react-router 6

The challenge I encountered was accessing the Meteor.user() in React Router's route loader property.

Alternatively, instead of querying the server, I'm picking up the user id from localStorage. The absence of it indicates the user is logged off or never logged in. Until Meteor kicks off, no sensitive data is displayed anyway.

...
{
  path: '/',
  element: <App />,
  errorElement: <ErrorPage />,
  loader: async () => window.localStorage.getItem('Meteor.userId'),
}
...

and in app.tsx:

const userId: UserId | null = useLoaderData()
const navigate = useNavigate()

useEffect(() => {
  if (userId === null) navigate('/login')
}, [userId])

How to run a node command from the UI Vision RPA Chrome extension

How to run a node command from the UI.Vision RPA chrome extension

The anatomy of a basic UI Vision task looks like this:

{
  "Command": "XType",
  "Target": "Hello World${KEY_ENTER}",
  "Value": "",
  "Description": ""
},

It can be a very simple task such as typing some text in the before-selected input control. But it can also perform advanced sequences. These sequences can involve conditional structures, and system calls. It can even execute javascript in a sandboxed context.

The two most important parameters are Value and Target. But sometimes its usage is not very intuitive.

Luckily, the documentation is clear and accessible. As a quick link next to the command dropdown.

Let's call a node.js process sometime in our automation flow.

To do this, make sure you have the UI Vision extra X Modules installed. If you're running this on mac, make sure to also grant the necessary permissions.

The inconsistent usage of Value and Target made me spend some time figuring out how to split the command. I've found that this works:

{
  "Command": "XRun",
  "Target": "/My Path/.n/bin/node",
  "Value": "/My Path/automations/my_automation.js",
  "Description": ""
},

The Target is the binary we want to run, and the Value is the parameter we want to pass to it. In our case, a javascript file.

Another mention-worthy caveat: In the Chrome extension, you can't pass the Terminal as Target process due to security concerns.

How to use DocumentFragment to render large lists faster

Using DocumentFragment does the trick because it isn't part of the active document tree structure.

This means it doesn't interact with the main document until mounted.

Hence, it doesn't impact the performance when changes occur to its contents.

// Setup
const outlet = document.getElementById('#myList');
const fragment = new DocumentFragment();
const results = fetchResults(); // returns Array<Result>

We then go through each result and prepare it properly:

results.map((result, index) => {
    const li = document.createElement('li');
    li.textContent = result;
    li.classList.add('result');
    // We append to the DocumentFragment
    fragment.appendChild(li);
 });

Finally, we append the end result to the list:

outlet.appendChild(fragment);

If we were to append each item to the list outlet within the map above, it would have triggered a repaint/reflow every time we performed the action.

Conditionally add properties to objects in JavaScript

This comes in handy when you want to completely omit a property from an object in case the value is undefined or null.

{prop1, prop2, ...(condition && prop3)}

The trick being here:

...(condition && prop3)

In case the condition evaluates to false, the property will be completely omitted from the object, otherwise, both the value and its corresponding key will show up in the end result.

Correctly grouping members within modules in JSDoc v3

JSDoc is great! It's documentation not so much. I needed a way to logically group together global methods and I was unsuccessful in finding a straightforward way in its official documentation.

Eventually, I've come across the following method, using @module and @member.

First, we define the module name, usually at the top of the file:

@module MyModule

We then proceed to annotate the target function with @memeber MyModule. One other important aspect is to also include @function along with the name of the function in order to appear in the module section.

/**
 * @member MyModule
 * @function myFunction
 ....
 */
 export const myFunction = () => ....