我如何使用用户脚本加载共享web worker?

我想用一个用户脚本加载一个共享的worker。 问题是用户脚本是免费的,并没有托pipe文件的商业模式 – 我也不想使用服务器,甚至是免费的服务器托pipe一个小文件。 无论如何, 我试了一下 ,我(当然)得到一个同样的来源政策错误:

Uncaught SecurityError: Failed to construct 'SharedWorker': Script at 'https://cdn.rawgit.com/viziionary/Nacho-Bot/master/webworker.js' cannot be accessed from origin 'http://stackoverflow.com'. 

还有另一种方法来加载一个networking工作者通过转换工作人员的function为一个string,然后到一个Blob和加载作为工人,但我也试过:

 var sharedWorkers = {}; var startSharedWorker = function(workerFunc){ var funcString = workerFunc.toString(); var index = funcString.indexOf('{'); var funcStringClean = funcString.substring(index + 1, funcString.length - 1); var blob = new Blob([funcStringClean], { type: "text/javascript" }); sharedWorkers.google = new SharedWorker(window.URL.createObjectURL(blob)); sharedWorkers.google.port.start(); }; 

而这也是行不通的。 为什么? 因为共享的工作人员是根据他们的工作文件从中加载的位置共享的。 由于createObjectURL为每个用途生成一个唯一的文件名 ,工作人员永远不会拥有相同的URL,因此永远不会被共享。

我该如何解决这个问题?


注:我试过询问具体的解决scheme,但在这一点上,我认为我能做的最好的是以更广泛的方式提出解决问题的办法,因为我所有的尝试解决scheme似乎根本不可能,方式URL.createObjectURL作品( 从规格 ,似乎不可能改变结果文件的URL)。

这就是说,如果我的问题可以以某种方式改善或澄清,请留下评论。

您可以使用fetch()response.blob()从返回的Blob创build一个types为application/javascriptBlob URL ; 将SharedWorker()参数设置为由URL.createObjectURL()创build的Blob URL ; 利用window.open()load新打开的window事件来定义原来window定义的同一个SharedWorker ,在新打开的window附加message事件到原来的SharedWorker

console尝试javascript 如何从另一个iFrame中清除iFrame的内容 ,其中当前的问题URL应该在新的tab上通过在consolelogging的worker.port.postMessage()事件处理程序的message从打开的window加载。

打开window也应该使用worker.postMessage(/* message */)从新打开的window发布message事件,同样在打开window

 window.worker = void 0, window.so = void 0; fetch("https://cdn.rawgit.com/viziionary/Nacho-Bot/master/webworker.js") .then(response => response.blob()) .then(script => { console.log(script); var url = URL.createObjectURL(script); window.worker = new SharedWorker(url); console.log(worker); worker.port.addEventListener("message", (e) => console.log(e.data)); worker.port.start(); window.so = window.open("https://stackoverflow.com/questions/" + "38810002/" + "how-can-i-load-a-shared-web-worker-" + "with-a-user-script", "_blank"); so.addEventListener("load", () => { so.worker = worker; so.console.log(so.worker); so.worker.port.addEventListener("message", (e) => so.console.log(e.data)); so.worker.port.start(); so.worker.port.postMessage("hi from " + so.location.href); }); so.addEventListener("load", () => { worker.port.postMessage("hello from " + location.href) }) }); 

在任一tab console ,你可以使用,例如; 如何从另一个iFrame worker.postMessage("hello, again")在当前URL的新window中清除iFrame的内容 如何使用用户脚本加载共享web worker? , worker.port.postMessage("hi, again"); 在每个window附加message事件的情况下,可以使用在初始URL创build的原始SharedWorker来实现两个window之间的通信。

前提

  • 正如您已经研究过的,并且在注释中提到的那样, SharedWorker的URL受SharedWorker策略的约束。
  • 根据这个问题 ,没有CORS支持Worker的URL。
  • 根据这个问题, GM_worker支持现在是一个WONT_FIX,并且由于Firefox的变化, 似乎已经足够接近于无法实现了。 还有一个注意,沙盒的Worker (而不是unsafeWindow.Worker )也无法正常工作。

devise

我想你想实现的是一个@include * userscript,它将收集一些统计信息或创build一些全球性的用户界面什么地方会出现。 因此,您希望有一名工作人员在运行时维护一些状态或统计聚合(这将很容易从每个用户脚本实例访问),并且/或者您想执行一些计算繁重的例程(否则它将会缓慢的目标网站下来)。

在任何解决scheme的方式

我想提出的解决scheme是用另一种方法replaceSharedWorkerdevise。

  • 如果你只想维护一个共享worker的状态,只需使用Greasemonkey存储( GM_setValue和friends)即可。 它在所有的用户脚本实例之间共享(SQLite隐藏场景)。
  • 如果你想做一些计算繁重的任务,把它放在unsafeWindow.Worker并把结果放回到Greasemonkey存储中。
  • 如果你想做一些后台计算,并且只能由单个实例运行,那么就有一些“inter-window”同步库(主要是使用localStorage但是Greasemomkey有相同的API,所以不应该很难写一个适配器)。 因此,你可以在一个脚本实例中获得一个锁,并在其中运行你的例程。 就像IWC或者ByTheWay ( 可能在Stack Exchange上使用这个function; 发布它 )。

另一种方式

我不确定,但可能有一些巧妙的响应欺骗,从ServiceWorker ,使SharedWorker工作,如你所愿。 起点是在这个答案的编辑 。

我很确定你想要一个不同的答案,但不幸的是,这是它归结为什么。

浏览器实施同源策略来保护互联网用户,虽然你的意图是干净的,但没有合法的浏览器允许你改变sharedWorker的来源。

sharedWorker所有浏览上下文必须共享完全相同的来源

  • 主办
  • 协议
  • 港口

你不能解决这个问题,我已经尝试使用iframes除了你的方法,但不会工作。

也许你可以把它放在Github上的JavaScript文件,并使用他们的raw. 服务来获取文件,这样你可以让它运行没有太多的努力。

更新

我正在阅读铬更新,我记得你问这个。 跨服务的工作人员到达铬!

为此,请将以下内容添加到SW的安装事件中:

 self.addEventListener('install', event => { event.registerForeignFetch({ scopes: [self.registration.scope], // or some sub-scope origins: ['*'] // or ['https://example.com'] }); }); 

还需要其他的一些考虑,检查一下:

完整链接: https : //developers.google.com/web/updates/2016/09/foreign-fetch?hl = zh-TW?utm_campaign = devshow_series_crossoriginserviceworkers_092316&utm_source=gdev&utm_medium=yt-desc