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

GWo*_*ing 0 javascript sorting freeze

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

list.sort(function (a,b) {return (a.value - b.value);});
Run Code Online (Sandbox Code Playgroud)

冻结浏览器几秒钟.

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

如何阻止激烈的Javascript循环冻结浏览器

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

*在评论讨论后编辑

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

tri*_*cot 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]
});
Run Code Online (Sandbox Code Playgroud)

非承诺版本如下所示:

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);
});
Run Code Online (Sandbox Code Playgroud)

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

onmessage = function (e) {
    e.data.sort();
    postMessage(e.data);
}
Run Code Online (Sandbox Code Playgroud)

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

new Worker('script.js')
Run Code Online (Sandbox Code Playgroud)