Failed to execute 'fetch' on 'WorkerGlobalScope'

筅森魡賤 提交于 2020-11-29 19:24:07

问题


I trying to fetch data from the server inside of a web worker. But in dev tools every time I got the same error.

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

I saw this answer about service workers, but it's not working for me.

WebWorker file code!

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

Imported in React component.

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

Running and posting messages inside of the hooks!

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

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

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

回答1:


Workers created from a blob:// URI have their baseURI set to set to that blob:// URI.

To fetch a relative URL the browser first has to build an absolute URI from the current realm's baseURI.

So in your case, the browser will try to generate an absolute URL from /api/books using blob:[origin]/[UUID] as the base. This is what throws:

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

To workaround that issue you have two options:

  • Use an absolute URL. This way you won't face that problem.

  • Pass the baseURI from your main thread to your Worker's script. This way you will be able to create the absolute URL yourself using the URL constructor.

The first option is really simple, so I guess you don't need an example. For the second, since we can't host relative files in StackSnippets, I had to host it in this plunker.

Here is the code:

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


来源:https://stackoverflow.com/questions/60836401/failed-to-execute-fetch-on-workerglobalscope

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!