Javascript多執行緒+非同步應用動態載入大量元素到Dom
/**
*【jQuery】deferred物件介紹及使用deferred物件解決ajax非同步問題
* https://www.gss.com.tw/blog/jquery%E9%80%9A%E9%81%8Edeferred%E7%89%A9%E4%BB%B6%E7%AE%A1%E7%90%86ajax%E9%9D%9E%E5%90%8C%E6%AD%A5
*/
var deferred = $.Deferred(),
deferred2 = $.Deferred();
var isCircleClick = false;
// Worker
if (window.Worker) {
var all = data.allGraph.length;
var curt = 0;
var loadingMsg = $("app-loading span").text();
/********************** multithread go go go **********************/
var numWorkers = 10;//執行緒數量
var workers = [];
var chunkCount = Math.floor(all / numWorkers);//整數除法
var deferred3s = [];//JQuery的非同步物件陣列
console.log(`[svgDraw] start time [thread count:${numWorkers}] => ${new Date()}`);
for (var i = 0; i < numWorkers; i++)
{
if (i == numWorkers - 1)
{//最後一個執行緒把餘數全部處理掉
var modValue = all % numWorkers;
if (modValue > 0)
{
chunkCount += modValue;
}
}
var chunkData = data.allGraph.splice(0, chunkCount);
/*
new Worker('assets/localhost_env_js/drawPCBWorker.js');//本機worker.js
new Worker('../Areas/Viewer/Scripts/drawPCBWorker.js');//uat worker.js
*/
var drawWorker = new Worker(drawPCBWorkerUrl);//宣告新執行緒,drawPCBWorkerUrl為執行緒要執行的工作流程.js
workers.push(drawWorker);
var deferred3 = $.Deferred();//建立JQuery非同步物件
deferred3s.push(deferred3);
//執行執行緒工作流程
drawWorker.postMessage([chunkData, basicStrokeWidth]);
(function (i, deferred3) {
//接收執行緒工作流程的回傳
drawWorker.onmessage = function (e) {
for (var i = 0; i < e.data.length; i++) {
/*
*錯誤範例!!!!!
*絕對不能+=1這樣累計,會嚴重拖累迴圈效能!!!!!
//curt += 1;
//$("app-loading span").html(`${loadingMsg}${curt}/${all}`)
*/
var combinGroup = myDocument.createElementNS(svgNS, "g");
setAttributes(combinGroup, {
"id": e.data[i].refdes,
"stroke": (e.data[i].PN == "" ? getLevelData("REFDES", "NOASSEMBLED").ColorCode : getLevelData(e.data[i].mainClass, e.data[i].subClass).ColorCode),
"class": e.data[i].mainClass + " " + e.data[i].subClass + (e.data[i].PN == "" ? " NOASSEMBLED" : ""),
"style": getLevelData(e.data[i].mainClass, e.data[i].subClass).Display == true ? 'display:inline;' : 'display: none;',
"bom": (e.data[i].mainClass != "VIA" ? e.data[i].Bom : ""),
"partnumber": (e.data[i].mainClass != "VIA" ? e.data[i].PN : ""),
"data-val": e.data[i]["data-val"],
"bWidth": e.data[i].bWidth,
"bHeight": e.data[i].bHeight,
"notice": e.data[i].notice ? e.data[i].notice : ""
});
if (e.data[i].mainClass === "VIA") {
combinGroup.setAttribute("data-test", e.data[i].isTestVia);
if (e.data[i].isTestVia !== undefined && e.data[i].isTestVia === false && my.showAllVia === false) {
combinGroup.setAttribute("class", combinGroup.getAttribute("class") + " none");
}
}
for (var j = 0; j < e.data[i].items.length; j++) {
for (var graph in e.data[i].items[j]) {
var dom = myDocument.createElementNS(svgNS, graph)
setAttributes(dom, e.data[i].items[j][graph]);
if (graph === "circle") {
var circle = dom;
circle.addEventListener("mousedown", function (e) {
isCircleClick = true;
});
circle.addEventListener("dblclick", function (e) {
getNetLineData(this.getAttribute("net"));
}, false);
}
combinGroup.appendChild(dom);
}
}
group.appendChild(combinGroup);
}
curt += e.data.length;
$("app-loading span").html(`${loadingMsg}${curt}/${all}`)
deferred3.resolve();
}
})(i, deferred3);
}
$.when.apply($, deferred3s).done(function () {
//等待所有JQuery非同步物件都完成工作
deferred.resolve();
console.log(`[svgDraw] end time => ${new Date()}`);
});
/********************** multithread end **********************/
}
ChatGPT範例
Qestion:javascript es3 多執行緒搭配jquery deferred如何使用
在 JavaScript ES3 环境中,无法直接使用现代 JavaScript 特性(例如 let
和 const
),但可以通过 Web Workers 实现多线程,并使用 jQuery Deferred 来管理异步操作。以下是一个示例,展示如何在 ES3 环境中使用 Web Workers 和 jQuery Deferred 进行多线程处理:
示例代码
Web Worker 文件 (worker.js
)
javascript
self.onmessage = function(event) {
var data = event.data;
var result = 0;
// 假设进行一些计算,这里仅做示范
for (var i = data.start; i < data.end; i++) {
result += i;
}
// 将结果发送回主线程
self.postMessage(result);
};
主线程代码 (main.js
)
javascript
$(document).ready(function() {
var numWorkers = 10;
var totalIterations = 100000;
var iterationsPerWorker = totalIterations / numWorkers;
var workers = [];
var deferreds = [];
var results = [];
var i;
// 创建 Web Workers 并分配任务
for (i = 0; i < numWorkers; i++) {
var worker = new Worker('worker.js');
workers.push(worker);
var deferred = $.Deferred();
deferreds.push(deferred);
worker.postMessage({ start: i * iterationsPerWorker, end: (i + 1) * iterationsPerWorker });
(function(i, deferred) {
worker.onmessage = function(event) {
results[i] = event.data;
deferred.resolve();
};
})(i, deferred);
}
// 使用 $.when.apply 方法处理 Deferred 数组
$.when.apply($, deferreds).done(function() {
var totalResult = 0;
for (i = 0; i < results.length; i++) {
totalResult += results[i];
}
console.log('All workers have completed their tasks.');
console.log('Total result:', totalResult);
});
});
解释
Web Worker 文件 (worker.js
):
self.onmessage
:处理从主线程接收到的消息。- 在接收到消息后执行计算,然后使用
self.postMessage
将结果发送回主线程。
主线程代码 (main.js
):
- 创建 10 个 Web Workers,每个 Worker 处理总循环的一部分。
- 使用
$.Deferred()
创建 Deferred 对象,并将它们添加到deferreds
数组中。 - 使用
postMessage
将循环范围分配给每个 Worker,并在 Worker 完成任务后解决对应的 Deferred。 - 使用
$.when.apply($, deferreds).done
等待所有 Deferred 对象完成,然后计算总结果并输出。
通过这种方式,您可以使用 Web Workers 实现多线程处理,并使用 jQuery Deferred 来管理异步操作和回调。这种方法在需要处理大量数据或执行复杂计算的情况下,可以提高性能。