2

I have a array of about 18 000 elements. I'm creating a map application where I want to add the elements when the user zooms in to a certain level.

So when the user zooms in under 9 I loop tru the array looking for elements that is in the view.

However, it does take some time looping thru the elements, causing the map application lag each time the user zooms out and in of "level 9". Even if there are no elements to add or not, so the bottleneck is the looping I guess.

I've tried to solve it by asyncing it like:

          function SearchElements(elementArr) {

                var ret = new Promise(resolve => {

                var arr = [];

                for (var i in elementArr) {

                    var distanceFromCenter = getDistanceFromLatLonInKm(view.center.latitude, view.center.longitude, dynamicsEntities[i].pss_latitude, dynamicsEntities[i].pss_longitude);
                    var viewWidthInKm = getSceneWidthInKm(view, true);

                    if (distanceFromCenter > viewWidthInKm) continue;

                    arr.push(elementArr[i]);
                }

                resolve(arr);
            });

            return ret;
        }

        SearchElements(myElementsArray).Then(arr => {
            // ... 
        });

But its still not async, this method hangs while the for loop runs.

fUrious
  • 434
  • 5
  • 14
  • I suppose/hope the `return re` instead of `return ret` is only a typo of your question. – Cédric Julien Sep 08 '17 at 10:21
  • 1
    Async and parallel is not the same. See [this answer](https://stackoverflow.com/a/6133590/3892935) for an explanation. – Coloured Panda Sep 08 '17 at 10:23
  • 3
    your code still has a presumably expensive (and synchronous) loop inside the promise `for (var i in elementArr) {` ... this will still cause the issue ... you need to break the job up into smaller chunks, or even use worker threads or whatever the kids are into these days :p – Jaromanda X Sep 08 '17 at 10:25
  • @JaromandaX I think this point could become an answer... maybe without the kids part, I think the kids grew wrinkles and/or beards already ;-) – Kos Sep 08 '17 at 10:27
  • Jaromanda X Hi, how can I use worker threads? – fUrious Sep 08 '17 at 10:28
  • I'm not one to ask about worker threads (or web workers, or whatever they are called) - I do have a proposed answer for my other suggestion – Jaromanda X Sep 08 '17 at 10:49

1 Answers1

2

Because you still have a tight loop that loops through all the elements in one loop, you'll always have the responsiveness issues

One way to tackle the issue is to works on chunks of the data

Note: I'm assuming elementArr is a javascript Array

function SearchElements(elementArr) {
    var sliceLength = 100; // how many elements to work on at a time
    var totalLength = elementArr.length;
    var slices = ((totalLength + sliceLength - 1) / sliceLength) | 0; // integer
    return Array.from({length:slices})
    .reduce((promise, unused, outerIndex) => 
        promise.then(results => 
            Promise.resolve(elementArr.slice(outerIndex * sliceLength, sliceLength).map((item, innerIndex) => {
                const i = outerIndex * sliceLength + innerIndex;
                const distanceFromCenter = getDistanceFromLatLonInKm(view.center.latitude, view.center.longitude, dynamicsEntities[i].pss_latitude, dynamicsEntities[i].pss_longitude);
                const viewWidthInKm = getSceneWidthInKm(view, true);
                if (distanceFromCenter <= viewWidthInKm) {
                    return item; // this is like your `push`
                }
                // if distanceFromCenter > viewWidthInKm, return value will be `undefined`, filtered out later - this is like your `continue`
            })).then(batch => results.concat(batch)) // concatenate to results
        ), Promise.resolve([]))
    .then(results => results.filter(v => v !== undefined)); // filter out the "undefined"
}

use:

SearchElements(yourDataArray).then(results => {
    // all results available here
});

My other suggestion in the comment was Web Workers (I originally called it worker threads, not sure where I got that term from) - I'm not familiar enough with Web Workers to offer a solution, however https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers and https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API should get you going

To be honest, I think this sort of heavy task would be better suited to Web Workers

Jaromanda X
  • 53,868
  • 5
  • 73
  • 87