javascriptfetchshared-worker

How can I execute a function every time fetch() is used in Javascript?


I am trying to post a message to my sharedWorker every time a HTTP request is made in my script to save me manually having to do it after every HTTP request.

I managed to get it working like so:

var App = {
    __webWorker: null,
    __XMLHttpRequest: XMLHttpRequest.prototype.open,
    __onScriptComplete: e       => {
        if( e.data.type && e.data.type === 'worker' ) {
            sessionStorage.setItem( 'token', e.data.session.token );
            return;
        }
    }
};

window.addEventListener( 'load', () => {
    XMLHttpRequest.prototype.open  = (method, url, async, user, password) => {
        App.__XMLHttpRequest(method, url, async, user, password);
        App.__webWorker.postMessage( '{{md5(session_id())}}' );
    };

    const worker = new SharedWorker( '{{$router->generate( 'web_notify_worker' )}}' );
    worker.port.onmessage = e => App.__onScriptComplete( e );
    App.__webWorker = worker.port;

    // The below gives me a Uncaught TypeError: Illegal invocation and the App.__webWorker.postMessage is executed
    let req = new XMLHttpRequest();
    req.open( 'GET', '/', true );
    req.send();

    // The below works fine but the App.__webWorker.postMessage is not executed
    fetch( '/', { method: 'GET' } );
} );

When I create a new XMLHttpRequest() this works fine and the sessionStorage item is set with the data. However, I do not use XMLHttpRequest, instead, I use fetch(). This seems to not create a XMLHttpRequest which I thought it would.

How can I execute a the postMessage function on my App.__webWorker every time a new fetch() is called? Preferably, after it is completed.

Update: This is my own framework, I used Smarty Template engine so ignore the {{}} prefixed areas. This is how I import data into the script from PHP.

Update: I have tried to do this, but I get Uncaught (in promise) TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation:

var App = {
    ...,
    __fetch: fetch
}

fetch = ( uri, args ) => {
    App.__fetch( uri, args );
    App.__webWorker.postMessage( '{{md5( session_id() )}}' );
};

Solution

  • You can override the override the global and call it. It would be a lot cleaner if you made it your own method and you call that instead of this 'hijacking

    const _fetch = window.fetch
    // window.fetch = function() {
    window.fetch = function(...args) {
      console.log('before fetch')
      // return Promise.resolve(_fetch.apply(window, arguments))
      return Promise.resolve(_fetch.apply(window, args))
        .then(resp => {
          console.log('inside then');
          return resp;
        })
    }
    
    fetch('https://jsonplaceholder.typicode.com/todos/1')
      .then(response => response.json())
      .then(json => console.log(json))