我的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));
}
答案 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
慢得多,但不会阻止主线程。