Не удалось выполнить «выборку» для «WorkerGlobalScope» - PullRequest
0 голосов
/ 24 марта 2020

Я пытаюсь получить данные с сервера внутри веб-работника. Но в инструментах разработки каждый раз я получал одну и ту же ошибку.

Uncaught (in promise) TypeError: Failed to execute 'fetch' on 'WorkerGlobalScope': Failed to parse URL from /api/books

Я видел этот ответ о сервисных работниках, но он не работает для меня.

Файл WebWorker код!

// data-handling.web-worker.js

const workercode = () => {
  onmessage = async e => {
    const res = await fetch('/api/books');

    postMessage(res);
  }
};

let code = workercode.toString();
code = code.substring(code.indexOf('{')+1, code.lastIndexOf('}'));

const blob = new Blob([code], {type: 'application/javascript'});
const worker_script = URL.createObjectURL(blob);

export default worker_script;

Импортировано в компонент React.

import data_handling_worker from "./data-handling.web-worker";
const dataHandlingWorker = new Worker(data_handling_worker);

Запуск и размещение сообщений внутри хуков!

const [searchQuery, setSearchQuery] = useState('');
const [booksList, setBooksList] = useState([]);

useEffect(() => {
  dataHandlingWorker.postMessage(searchQuery);
}, [searchQuery]);

useEffect(() => {
  dataHandlingWorker.onmessage = (m) => {
    setBooksList(m.data);
  };
}, []);

1 Ответ

1 голос
/ 25 марта 2020

Для рабочих, созданных из blob:// URI, для baseURI установлено значение blob:// URI .

Чтобы получить относительный URL, браузер сначала должен создать абсолютный URI из текущей области baseURI.

Так что в вашем случае браузер попытается сгенерировать абсолютный URL из /api/books используя blob:[origin]/[UUID] в качестве базы. Это то, что бросает :

const worker_script = `
  postMessage( { baseURI: self.location.href } );
  try {
    const absolute = new URL( "api/books", self.location.href );
  }
  catch( err ) {
    postMessage( { err: err.toString() } );
  }
`;
const worker_url = URL.createObjectURL( new Blob( [ worker_script ] ) );
const worker = new Worker( worker_url );
worker.onmessage = (evt) => console.log( evt.data );

Чтобы обойти эту проблему, у вас есть два варианта:

  • Использовать абсолютный URL. Таким образом, вы не столкнетесь с этой проблемой.

  • Передайте baseURI из основного потока в сценарий вашего работника. Таким образом, вы сможете создать абсолютный URL-адрес самостоятельно, используя URL-конструктор .

Первый вариант очень прост, так что, думаю, вам не нужно пример. Во-вторых, поскольку мы не можем разместить относительные файлы в StackSnippets, мне пришлось разместить его в этом плункере .

Вот код:

const worker_script = `
  onmessage = (evt) => {
    const base = evt.data;
    const absolute = new URL( "api/books", base );
    fetch( absolute )
      .then( (resp) => resp.text() )
      .then( (txt) => postMessage( txt ) )
      .catch( console.error );
  };
`;
const worker_url = URL.createObjectURL( new Blob( [ worker_script ] ) );
const worker = new Worker( worker_url );
worker.onmessage = (evt) => document.body.append( evt.data );
// pass the main thread's baseURI
worker.postMessage( document.baseURI );
...