Chrome 无法加载 web worker

我正在做一个项目,使用一个网络工作者。

在我的头部我有这样的代码:

var worker = new Worker("worker.js");
// More code

这在 Safari 中运行良好,但 Chrome 报告了以下错误:

Uncaught SecurityError: Failed to create a worker: script at '(path)/worker.js' cannot be accessed from origin 'null'.

为什么这个在 Safari 中工作的很好,但是在 Chrome 中却不行? 我该怎么解决这个问题?

谢谢你。

99485 次浏览

当从本地文件运行脚本时,Chrome 不允许加载 web worker。

我也有和你一样的问题。解决方案是必须使用 localhost (wamp 或 xamp)运行它。没问题。

这个问题已经被 Noble Chicken 恰当地解释过了,但是我有一个更普遍的解决方案。与安装 wamp 或 xamp 不同,使用 python 可以导航到项目所在的文件夹并键入: python -m http.server

仅此而已,您将在该文件夹上有一个正在运行的服务器,可以从 localhost 访问。

你需要一个网络服务器从 HTTP 协议的请求,而不是本地文件 并且正确地工作:)

由于 Python 2.x 比 Python 3.x 部署得更广泛,所以类似 python -m SimpleHTTPServer 8000的东西更普遍地适用,而且不仅仅适用于 Mac OS X。例如,我发现在 Cygwin 下使用它是必要的。

有了这个,这个例子运作得非常好。

加载文件,但无法运行它。使用 Firefox。它为我工作。

我用了变通方法。铬能阻挡 Worker但不能阻挡 <script>。因此,制定一个普遍解决方案的最佳方法是:

function worker_function() {
// all code here
}
// This is in case of normal worker start
// "window" is not defined in web worker
// so if you load this file directly using `new Worker`
// the worker code will still execute properly
if(window!=self)
worker_function();

然后把它作为正常的 <script src="..."链接起来。一旦定义了函数,你就可以使用这种令人厌恶的代码:

new Worker(URL.createObjectURL(new Blob(["("+worker_function.toString()+")()"], {type: 'text/javascript'})));

你也可以在启动 Chrome 时使用 —— allow-file-access-from-files标志。

以 MacOsX 为例:

/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --allow-file-access-from-files

更多信息: 网络工作者设置的铬

一个可能的原因是,当从本地文件运行脚本时,chrome 不允许你加载 web worker。我尝试在我的火狐上运行代码,也不能。

这是由于安全限制。您需要使用 http://https://协议而不是 file:///

如果已经安装了 NodeJS,只需执行以下操作。 - 注意,这只是众多选项中的一个

安装 本地-网络-服务器

$ npm install -g local-web-server

现在您可以在希望通过 http访问内容的任何文件夹中使用它。

$ ws

导航到 http://localhost:8000(默认端口: 8000)

是的,如果你正在加载本地文件,它不会在 chorome 中工作。但是在 Firefox 浏览器中可以正常工作。并且必须在 HTML 文件中添加以下代码。

<head>
<meta charset="UTF-8" />
</head>

另一个解决方案是使用谷歌的 Chrome 浏览器的网页服务器扩展。选择您的工作目录并启动服务器,完成!

function worker_fun(num){
num ++
// console.log(num)
postMessage(num);
setTimeout(worker_fun.bind(null,num), 500)
}


var w


function startWorker(){
var blob = new Blob([
"onmessage = function(e){\
" + worker_fun.toString() + "\
worker_fun(e.data.num);}"
]);
var blobURL = window.URL.createObjectURL(blob);
if (typeof(Worker) != 'undefined'){
if (typeof(w) == 'undefined'){


w = new Worker(blobURL);
w.onmessage = function(event){
document.getElementById('num').innerHTML = event.data;
}
w.postMessage({
num:parseInt(document.getElementById('num').innerHTML)})
}
}
}




function stopWorker() {
w.terminate();
w = undefined;
}

如前所述,铬不支持它。我喜欢在同一个文件中定义我的工人。这是一个工作解决方案,每隔500毫秒就会增加 innerHTML 中具有 id=num的元素的数量。

制作 本地 http 服务器的简单方法是这个应用程序:

Chrome 网络服务器

Https://chrome.google.com/webstore/detail/web-server-for-chrome/ofhbbkphhbklhfoeikjpcbhemlocgigb/related

描述:

Chrome 的 Web 服务器,通过网络从本地文件夹服务网页,使用 HTTP。离线运行。 Web Server for Chrome 是一个用于 Chrome 的开源(MIT) HTTP 服务器。

它可以运行在你安装了 Chrome 的任何地方,所以你可以把它带到任何地方,它甚至可以在 ARM Chromebook 上运行。

它现在可以选择监听本地网络,这样其他计算机就可以访问您的文件。此外,它还可以尝试获得一个互联网地址。

许多人用这个在 Chromebook 上做基本的网页开发。它还可以方便地通过计算机之间的本地网络,甚至在互联网上共享文件。

安装完成后,导航到 http://127.0.0.1:8887

它并不像 —— allow-file-access-from-files标志那样不安全

这是受到上述托马斯回答的启发,但有一点需要注意 我想只分发 HTML,所以我 手动将 js 转换为 dataURL。并启用数据 URL 复选框在其中。

const myWorker = new Worker("data:application/x-javascript;base64,b25tZXNzYW...");

为了从使用 Webpack 和 TypeScript 建立的项目中的文件中加载 web worker,我按照 Tomáš Zato 的建议使用了一个脚本。但是,我必须修改工作文件。

工人

(() => {
console.log("worker_function loaded");
// @ts-ignore
window.worker_function = () => {
self.onmessage = ({ data: { question } }) => {
// @ts-ignore
self.postMessage({
answer: 42,
});
};
}
})();

Index.ts

async function run() {
console.log('run()');


const worker = new Worker(
// @ts-ignore
URL.createObjectURL(new Blob(["("+worker_function.toString()+")()"], { type: 'text/javascript' }))
);


worker.postMessage({
question: 'The Answer to the Ultimate Question of Life, The Universe, and Everything.',
});
worker.onmessage = ({ data: { answer } }) => {
console.log(answer);
};
}


run();

Html

<html lang="en-us">
<head>
<meta charset="utf-8" />
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<title>Offscreen canvas with web worker sample project</title>
<script async type="text/javascript" src="worker.js"></script>
<script async type="text/javascript" src="app.js"></script>
</head>
<body>
<h1>web worker sample project</h1>
</body>
</html>

Config.js (版本5)

const path = require("path");
const CopyPlugin = require("copy-webpack-plugin");


module.exports = {
mode: "production",
entry: {
app: "./src/index.ts",
worker: "/src/worker.ts"
},
output: {
filename: "[name].js",
path: path.resolve(__dirname, "build")
},
performance: {
hints: false
},
module: {
rules: [
{
test: /\.tsx?$/,
use: "ts-loader",
exclude: /node_modules/
},
]
},
resolve: {
extensions: [".js", ".ts"]
},
plugins: [
new CopyPlugin({
patterns: [
{ from: "src/index.html", to: "" }
]
})
]
};