Javascript,如何编写一个Array.sort方法,以便通过超时策略调用它?

时间:2016-08-28 10:10:36

标签: javascript sorting freeze

我的sort()函数存在瓶颈,例如:

list.sort(function (a,b) {return (a.value - b.value);});

冻结浏览器几秒钟。

对于循环的相同情况,建议使用“超时”策略,例如此处描述的策略:

How to stop intense Javascript loop from freezing the browser

然后,问题是,这可以用排序方法实现吗?

*在评论讨论后编辑

// main_div is a div defined before
for (let i=0; i<list.length; i++) {
    main_div.appendChild(document.getElementById(list[i].id));
}

2 个答案:

答案 0 :(得分:5)

您可以使用本机sort方法执行排序,但是在单独的线程中,使用Web worker。 Web工作人员将在完成其工作时通知。我已将其包含在ES6承诺中,因此您可以使用then方法(请参阅下面的非承诺版本):

function asyncSort(data) {
    // Return a promise
    return new Promise(function (resolve) {
        // function to be called by web worker:
        function onmessage(e) {
            e.data.sort();
            postMessage(e.data);
        }
        // Create the worker, passing it the above code (as blob URL)
        var worker = new Worker(URL.createObjectURL(
            new Blob(['onmessage = ' + onmessage.toString()])));
        // Capture the event when worker has finished
        worker.onmessage = function (e) { 
            resolve(e.data); // resolve the promise
        };
        // Let worker execute the sort (async)
        worker.postMessage(data);
    });
}

// Sample call
asyncSort([2, 3, 1]).then(function (result) {
    console.log(result); // [1, 2, 3]
});

非承诺版本如下所示:

function asyncSort(data, callback) {
    function onmessage(e) {
        e.data.sort();
        postMessage(e.data);
    }
    var worker = new Worker(URL.createObjectURL(
        new Blob(['onmessage = ' + onmessage.toString()])));
    worker.onmessage = function (e) { 
        callback(e.data);
    };
    worker.postMessage(data);
}

asyncSort([2, 3, 1], function (result) {
    console.log(result);
});

请注意,IE(至少版本11)会在Blob URL上引发安全性错误。作为解决方法,您必须使用以下内容创建单独的JS脚本文件:

onmessage = function (e) {
    e.data.sort();
    postMessage(e.data);
}

...然后将该脚本作为原始脚本中Worker的URL引用:

new Worker('script.js')

答案 1 :(得分:2)

您可以实现自己的排序功能,例如,这里有一个简单的选择排序:

function asort(a, compare, done) {
    var i = 0, j = 0, len = a.length;

    function step() {
        if(j >= len)
            [i, j] = [i + 1, i + 1];
        if(i >= len)
            return done();
        if(compare(a[j], a[i]) < 0)
            [a[i], a[j]] = [a[j], a[i]]
        j++;
        setTimeout(step, 0);
    };

    step();
}

这比股票sort慢得多,但不会阻止主线程。