不是真正的异步?

时间:2017-09-08 10:19:50

标签: javascript asynchronous

我有一个大约18 000个元素的数组。我正在创建一个地图应用程序,我想在用户放大到某个级别时添加元素。

因此,当用户在9以下放大时,我会循环查找数组中的元素。

但是,通过元素循环需要一些时间,导致每次用户缩小并处于“级别9”时地图应用程序滞后。即使没有要添加的元素,所以瓶颈就是我想的循环。

我试图像它一样解决它:

          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 => {
            // ... 
        });

但它仍然没有异步,这个方法在for循环运行时挂起。

1 个答案:

答案 0 :(得分:2)

因为你仍然有一个紧密的循环遍历一个循环中的所有元素,你总会有响应问题

解决问题的一种方法是处理数据块

注意:我假设elementArr是一个javascript数组

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"
}

使用:

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

我在评论中提出的其他建议是Web Workers(我最初称之为工作线程,不知道我从哪里获得该术语) - 我对Web Workers不太熟悉,无法提供解决方案,{{3 }和https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers应该让你去

  

老实说,我认为这种heavy任务更适合Web Workers