Files
001code-html--cocos/scratch-gui/static/js/PyodideWorkerPool.js
刘宇飞 6e0a1fbcbb Initial commit of 001code-html Scratch frontend project.
Includes scratch-gui, scratch-vm, scratch-blocks, scratch-render, scratch-l10n, and deployment config.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 15:37:45 +08:00

87 lines
2.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// PyodideWorkerPool.js
export default class PyodideWorkerPool {
constructor(poolSize = 2) {
this.poolSize = poolSize;
this.workers = [];
this.onMessageCallbacks = [];
this.initPool();
}
initPool() {
for (let i = 0; i < this.poolSize; i++) {
this.workers.push(this.createWorker());
}
}
createWorker() {
const workerInfo = {
worker: new Worker('js/pyodideWorker.js'),
busy: false,
loaded: false
};
// 监听 Worker 消息
workerInfo.worker.onmessage = (event) => {
const { type } = event.data;
if (type === "finish") {
workerInfo.loaded = true;
}
if (type === "executionComplete" || type === "error") {
workerInfo.busy = false;
}
// 让外部知道“是哪个 worker 发来的消息”
for (let cb of this.onMessageCallbacks) {
cb(event, workerInfo);
}
this.updateIsPythonLoadOK();
};
return workerInfo;
}
addOnMessageListener(callback) {
this.onMessageCallbacks.push(callback);
}
updateIsPythonLoadOK() {
// 只要至少一个 Worker loaded 就算可以执行
const anyLoaded = this.workers.some(w => w.loaded === true);
window.isPythonLoadOK = anyLoaded;
}
// 找到不忙、且已loaded的 Worker
getFreeWorker() {
return this.workers.find(w => w.busy === false && w.loaded === true) || null;
}
// 让指定 Worker 执行
runPython(workerInfo, code) {
if (workerInfo.busy) {
throw new Error("该 Worker 正在执行脚本,无法重复使用");
}
if (!workerInfo.loaded) {
throw new Error("该 Worker 尚未加载 Pyodide无法执行 Python");
}
workerInfo.busy = true;
workerInfo.worker.postMessage({ type: "runPython", code });
}
// 停止并替换
terminateAndReplace(workerInfo) {
workerInfo.worker.terminate();
const idx = this.workers.indexOf(workerInfo);
if (idx !== -1) {
const newW = this.createWorker();
this.workers[idx] = newW;
}
this.updateIsPythonLoadOK();
}
destroyPool() {
for (let wInfo of this.workers) {
wInfo.worker.terminate();
}
this.workers = [];
this.updateIsPythonLoadOK();
}
}