Chrome не может загрузить веб-работника

Я работаю над проектом, который использует веб-работника.

В моем разделе головы у меня есть этот код:

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? Как это исправить?

Спасибо.

16 ответов

Решение

Chrome не позволяет загружать веб-работников при запуске сценариев из локального файла.

Я использую обходной путь. Хромированные блоки 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'})));

Noble Chicken правильно объяснил проблему, но у меня есть более общее решение. Вместо установки wamp или xamp, с помощью python вы можете перейти к папке, в которой находится ваш проект, и набрать: python -m http.server

Просто у вас будет запущенный сервер в этой папке, доступный из localhost.

Вы также можете использовать флаг --allow-file-access-from-files при запуске Chrome.

Пример для MacOsX:

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

Дополнительная информация: настройки веб-рабочего для Chrome

Это из-за ограничений безопасности. Вам нужно использовать http:// или же https:// протокол вместо file:///,

Если у вас установлен NodeJS, вы можете просто сделать следующее. - Обратите внимание, что это один из многих доступных вариантов

Установить локальный веб-сервер

$ npm install -g local-web-server

Теперь вы можете использовать его в любой папке, к которой вы хотите получить доступ через http ,

$ ws

Перейдите к http://localhost:8000 (порт по умолчанию: 8000)

У меня была такая же проблема, как и ваш пост. Решение заключается в том, что вы должны запустить его с localhost (wamp или xamp). Это будет сделано.

Это вдохновлено ответом Томаса выше. Но с одной оговоркой, что я хотел распространять только HTML, поэтому я вручную преобразовал js в dataURL. и установите в нем флажок URL-адреса данных.

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

Другой обходной путь - использование веб-сервера Google для расширения Chrome. Выберите свой рабочий каталог и запустите сервер, Готово!

Простой способ сделать локальный http-сервер в Chrome это приложение:

Веб-сервер для Chrome

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

Описание:

Веб-сервер для Chrome обслуживает веб-страницы из локальной папки по сети, используя HTTP. Работает в автономном режиме. Web Server для Chrome - это HTTP-сервер с открытым исходным кодом (MIT) для Chrome.

Он работает везде, где у вас установлен Chrome, так что вы можете взять его где угодно. Это даже работает на хромбуках ARM.

Теперь у него есть возможность прослушивания в локальной сети, чтобы другие компьютеры могли получить доступ к вашим файлам. Кроме того, он может попытаться получить интернет-адрес.

Многие люди используют это, чтобы сделать основные веб-разработки на Chromebook. Это также удобно для обмена файлами по локальной сети между компьютерами или даже в Интернете.

После установки перейдите на http://127.0.0.1:8887/

И это не небезопасно, так как флаг --allow-file-access-from-files

Вам нужен веб-сервер для запроса по протоколу HTTP вместо локального файла и работает правильно:)

Chrome загрузить файл, но не могу его запустить. использование Firefox, Это работает для меня.

С Python 2.x более широко развернутым, чем Python 3.x, что-то вроде python -m SimpleHTTPServer 8000 в более широком смысле, и не только для Mac OS X. Я нашел это необходимым для использования, например, в Cygwin.

С этим, этот пример работал как чемпион.

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;
}

Как уже упоминалось, хром не поддерживает его. Мне нравится определять моих работников в одном файле. Это рабочий обходной путь, который увеличит число, найденное в innerHTML элемента с id=num каждые 500 мс.

Вероятно, причина в том, что Chrome не позволяет загружать веб-работников при запуске сценариев из локального файла. И я пытаюсь запустить код на моем Firefox, тоже не могу.

Чтобы загрузить веб-воркер из файла в проекте, настроенном с помощью Webpack и TypeScript, я использовал скрипт, предложенный Томашем Зато. Однако мне пришлось изменить рабочий файл.

рабочий.тс

      (() => {
    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();

index.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>

webpack.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: "" }
      ]
    })
  ]
};

Да, он не будет работать в chorome, если вы загружаете локальный файл. Но это будет хорошо работать в браузере Firefox. И вы должны добавить ниже код в файле HTML.

<head>
    <meta charset="UTF-8" />
</head>
Другие вопросы по тегам