1

每次在我的脚本中发出 HTTP 请求时,我都会尝试向我发布一条消息,sharedWorker以节省我在每次 HTTP 请求后必须手动执行的操作。

我设法让它像这样工作:

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

当我创建一个new XMLHttpRequest()这工作正常并且该sessionStorage项目是用数据设置的。但是,我不使用XMLHttpRequest,而是使用fetch(). 这似乎并没有创造出XMLHttpRequest我认为的那样。

每次调用 new 时,如何postMessage在 my 上执行该函数?最好是在完成之后。App.__webWorkerfetch()

更新:这是我自己的框架,我使用 Smarty 模板引擎,所以忽略{{}}前缀区域。这就是我从 PHP 将数据导入脚本的方式。

更新:我试图这样做,但我得到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() )}}' );
};
4

2 回答 2

2

您可以覆盖覆盖全局并调用它。如果您将其设为自己的方法并调用它而不是这种“劫持”,那会更干净

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

于 2020-07-27T20:45:26.950 回答
1

经过一些广泛的谷歌搜索,我发现问题在于将 存储fetchApp范围内。要解决此问题,您必须将其存储在window范围内。

_fetch = fetch;

fetch = ( uri, args ) => {
    let f = _fetch( uri, args );
    App.__webWorker.postMessage( '{{md5( session_id() )}}' );
    return f;
};

这样就可以正常工作,每次fetch()发送 a 时,sharedWorker都会发布一条消息。

于 2020-07-27T20:44:20.317 回答