我是Web Worker的新手,现在我想做的是导入我在Web Worker中的workerCode下创建的函数,但“import”和“importScript”都不起作用;只有 XLSX 库工作正常,但其余部分则不然。
你能帮我弄清楚该怎么做吗?
export const consolidateWorkerV2 = () => {
const workerCode = `
/* Load standalone script from CDN */
import * as XLSX from "https://cdn.sheetjs.com/xlsx-0.20.1/package/xlsx.mjs";
import getDataRange from "../shared/util/GetDataRange";
import modifyWorksheet from "../shared/util/modifyWorksheet.js";
import headerStyling from "../shared/util/headerStyling";
self.addEventListener('message', async (e) => {
try {
const files = e.data.files;
const newWorkbook = XLSX.utils.book_new();
console.log("message received from main thread");
for (const [index, item] of files.entries()) {
const file = item.file;
const filename = item.file.name
const data = await item.file.arrayBuffer();
const workbook = XLSX.read(data);
for (const sheetName of workbook.SheetNames) {
if (newWorkbook.SheetNames.includes(journalType)) {
const duplicateSheetName = workbook.SheetNames[0];
const newWorksheet = newWorkbook.Sheets[journalType];
const dupWorksheet = getDataRange(workbook.Sheets[duplicateSheetName]);
const OPTIONS = { raw: false, defval: "", };
const parsedDupWorksheet = XLSX.utils.sheet_to_json(dupWorksheet, OPTIONS);
const updatedWorksheet = modifyWorksheet(dupWorksheet, parsedDupWorksheet, duplicateSheetName, journalType, reportDate);
const newData = updatedWorksheet.map((row) => Object.values(row));
XLSX.utils.sheet_add_aoa(newWorksheet, newData, { origin: -1, skipHeader: true });
} else {
// if no existing sheet name, then add new sheet
for (const sheetName of workbook.SheetNames) {
const worksheet = workbook.Sheets[sheetName];
const worksheetData = getDataRange(worksheet);
const parsedWorksheet = XLSX.utils.sheet_to_json(worksheet, { raw: false, defval: "", });
const updatedWorksheet = modifyWorksheet(worksheetData, parsedWorksheet, sheetName, journalType, reportDate);
const styledSheet = headerStyling(updatedWorksheet);
XLSX.utils.book_append_sheet(newWorkbook, styledSheet, journalType);
}
}
}
}
const consolidateFilename = namingConvention("Consolidated_Final_Report", date);
const excelBuffer = XLSX.write(newWorkbook, { bookType: "xlsx", type: "array", });
const blob = new File([excelBuffer], fileName + ".xlsx");
postMessage({ blob: blob });
} catch(e) {
/* Pass the error message back */
postMessage({ error: String(e.message || e).bold() });
}
}, false);
`;
const blob = new Blob([workerCode], { type: "text/javascript" });
const worker = new Worker(URL.createObjectURL(blob), { type: "module" });
return worker;
};
我看到两个问题:
当不涉及捆绑程序时,您必须包含通过
import
或 importScripts
导入的模块的完整文件名;本机网络平台不会尝试猜测文件扩展名。所以你需要:
import getDataRange from "../shared/util/GetDataRange.js";
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^
...假设这是资源的完整路径。
我找不到它的具体引用,但我相信当你通过 blob 加载工作人员时,你不能使用相对导入。四种可能的互斥解决方案:
不要使用 Blob,为以通常方式加载的工作线程使用单独的脚本:
const worker = new Worker("./path/to/worker.js", { type: "module" });
这是简单易行的答案。
如果您只需要在单个站点上运行此代码,请像使用
XLSX
库一样使用绝对导入。例如:
import getDataRange from "https://example.com/shared/util/GetDataRange.js";
或类似的。
在创建 Blob 之前修改
workerCode
以将相对路径替换为绝对路径:
let workerCode = /*...*/;
const shared = new URL("../shared", location.href).toString();
workerCode = workerCode.replace(/from "\.\.\/shared/g, `from ${shared}`);
// ...build the worker
使用
self.origin
获取工作线程中的源(快速测试表明这适用于 Chromium、Firefox 和 Safari)并使用 动态导入。
const getDataRange = (await import(new URL("../shared/util/GetDataRange", self.origin).toString())).default;
我怀疑其他三种解决方案中的任何一种都比这个更好,但同样,它似乎确实适用于主要浏览器。