HTML5 Zone is brought to you in partnership with:

Software developer and solutions designer of large distributed systems and frameworks. Luis is a DZone MVB and is not an employee of DZone and has posted 7 posts at DZone. You can read more from them at their website. View Full User Profile

Wishing For A Lazier Underscore

06.25.2014
| 4475 views |
  • submit to reddit

Sometimes the day of a developer gets awfully complicated. One of my less favorite moments are those when you have used a library for most of your project and then you realize you need things from it it was not designed to do. I was in this particular position last week, trying to stretch UnderscoreJS in ways it just wasn’t designed to bend.

Don’t get me wrong, I love UnderscoreJS, it brings the sweetness of C#’s LINQ-style chained queries to JavaScript arrays. If it was a person, I would totally hug it. But it made me smash my head against the wall a couple times when I realized that it lacks lazy evaluation of chained queries.

Why would I need that, you ask? Because sometimes I have to accomplish the darnest requirements. The original culprit was Kendo UI, an awesome UI-widget library by the guys at Telerik. The issue is that I had to completely override its built-in filtering mechanism since I needed it to be able to filter a data source in a master-detail fashion. For example, I have an array of customers, each customer has a sub-array of products it has bought. The grid displays a master row per-customer and detail rows for the products it has bought. Even so, the user should be able to filter by product, so if any customer had bought a particular product, it should be listed in the grid.

As long as I (and Google) know, this cannot be done out-of-the-box with Kendo UI unless you do it manually on server-side, since it can filter over all of the object properties, but not sub-arrays.

After some work, I managed to override the default filters and the original filter method in the grid’s data source. However, I needed a fast way to filter the data source like the original filtering mechanism did, so I recurred to UnderscoreJS. Performance was not that good; after wrapping the data source in an UnderscoreJS chain, I had to apply the filter method once per filter applied on the grid. The more filters, the worst performance got.

I eventually figured out that every time I was calling the filter function, it was iterating once over the entire data source. Of course performance was bad. Really dumb of me, since I was used to how LINQ worked; it allowed me to build a query in a fluent fashion and then execute it over the data source so it was iterated over just once. This process is called lazy evaluation of a query over a data source. UnderscoreJS does NOT feature lazy evaluation.

var filteredCustomers = 
    _(this.customers)
        .filter(function (customer) { // Iterates the array once...
            return customer.firstName === 'Luis';
        })
        .filter(function (customer) { // And then again...
            return customer.lastName === 'Aguilar';
        })
        .filter(function (customer) { // And again...
            return _(customer.products).any(function (product) { // LOL don't even ask...
                return product.name === 'Time Machine X9000-S'
            });
        });

I think the only thing left to do is to use another library to support my custom filtering mechanism. Sigh. I’ll let you know of my findings…

Published at DZone with permission of Luis Aguilar, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)