2012-07-06 139 views
25

我們可以使用像這樣的HTML5網頁工人:Web Worker爲什麼不能直接調用一個函數?

var worker = new Worker('worker.js'); 

,但爲什麼我們不能稱這樣的功能?

var worker = new Worker(function(){ 
    //do something 
}); 
+2

另一個可以幫助你的插件是[vkThread](http://www.eslinstructor.net/vkthread/)。看看[http://www.eslinstructor.net/vkthread/](http://www.eslinstructor.net/vkthread/)你會在那裏找到例子和文檔。 – vadimk 2013-09-16 06:53:46

+0

您需要使用URL,但某些瀏覽器將允許您使用BLOB URL。有關示例,請參見[this](http://stackoverflow.com/a/6454685/19676)回答。 – Maurice 2012-07-06 06:56:02

+0

正如@Qix在另一個人所說的迴應評論中所說,vkThread也是基於function.toString,這會導致瀏覽器之間的不一致。 – 2015-06-18 09:30:19

回答

17

這是網絡工作者設計的方式。他們必須擁有自己的外部JS文件以及由該文件初始化的自己的環境。由於多線程衝突的原因,他們無法與常規全局JS空間共享環境。

網絡工作者不允許直接訪問你的全局變量的一個原因是,它需要兩個環境之間的線程同步,這是不是可用的東西(它會使事情變得非常複雜)。當Web工作者擁有自己獨立的全局變量時,除了通過與主JS線程正確同步的消息傳遞隊列之外,他們不能混淆主JS線程。也許有一天,更高級的JS程序員將能夠使用傳統的線程同步技術來共享對公共變量的訪問,但是現在,兩個線程之間的所有通信都必須經過消息隊列,並且web worker不能訪問主要的Javascript線程的環境。

+0

同意,我們有一段時間了,但已經走了。 – 2012-07-06 02:23:03

+0

我認爲javascript是單線程的。但是大容器可以打開並運行多線程頁面。所以我猜web worker會創建一個新頁面(或者稱之爲新環境)並在其中運行腳本?所以網絡工作者可以調用一個外部的JS文件。 – Dozer 2012-07-06 02:42:01

+0

@Dozer - 基本上是正確的。主要的JavaScript線程是單線程的,網絡上的很多JavaScript代碼都假設這一點。與其添加高級線程同步工具以允許通用多線程,那些設計Web工作者的人決定採取更小的步驟並允許新的線程,但只有當它通過新的JS文件初始化它自己的全局環境並且不能與任何全局訪問共享主線程除非通過消息隊列同步。這可以防止線程間的全局變量同步問題。 – jfriend00 2012-07-06 02:51:43

8

這個問題已經被問before,但由於某些原因,OP決定將其刪除。
我轉發我的答案,以防萬一需要從函數創建Web工作者的方法。


this post中,顯示了三種方式來從任意字符串創建Web Worker。在這個答案中,我使用了第三種方法,因爲它在所有環境中都受支持。

需要一個幫手文件:

// Worker-helper.js 
self.onmessage = function(e) { 
    self.onmessage = null; // Clean-up 
    eval(e.data); 
}; 

在您的實際工作者,這個輔助文件的使用方法如下:

// Create a Web Worker from a function, which fully runs in the scope of a new 
// Worker 
function spawnWorker(func) { 
    // Stringify the code. Example: (function(){/*logic*/}).call(self); 
    var code = '(' + func + ').call(self);'; 
    var worker = new Worker('Worker-helper.js'); 
    // Initialise worker 
    worker.postMessage(code); 
    return worker; 
} 

var worker = spawnWorker(function() { 
    // This function runs in the context of a separate Worker 
    self.onmessage = function(e) { 
     // Example: Throw any messages back 
     self.postMessage(e.data); 
    }; 
    // etc.. 
}); 
worker.onmessage = function() { 
    // logic ... 
}; 
worker.postMessage('Example'); 

注意,範圍是嚴格分開的。變量只能使用worker.postMessageworker.onmessage來傳遞。所有消息都是structured clones

+0

這裏假定'Function.toString()'作爲一個un-eval反編譯器,在某些環境中情況並非如此。謹慎使用! – Qix 2014-11-03 22:52:22

+0

@Qix如果您可以命名至少一個支持Web Workers的通用瀏覽器,但您的評論會更有幫助,但默認情況下,用戶定義的函數上的'toString()'不會返回功能相同的源代碼。 – 2014-11-03 23:18:36

+0

瀏覽器不是唯一的Javascript環境。事實是,這違反了W3C標準以及Ecmascript標準(功能不應該被反編譯;支持它的環境只能作爲用於調試目的的附加功能)。 – Qix 2014-11-04 02:47:29

3

這個答案可能有點晚,但我寫了一個庫來簡化網絡工作者的使用,它可能適合OP的需要。檢查出來:https://github.com/derekchiang/simple-worker

它允許你做這樣的事情:

SimpleWorker.run({ 
    func: intensiveFunction, 
    args: [123456], 
    success: function(res) { 
    // do whatever you want 
    }, 
    error: function(err) { 
    // do whatever you want 
    } 
}) 
+0

這看起來很像@ vadimk的vkThread上面的帖子 - 顯然不同的項目,但我可以說vkThread工作得很好,並有幾種不同的使用方法。 – Nick 2013-10-17 10:43:56

0

只要用我的小插件https://github.com/zevero/worker-create

,做

var worker_url = Worker.create(function(e){ 
    self.postMessage('Example post from Worker'); //your code here 
}); 
var worker = new Worker(worker_url); 
1

雖然它不是最佳的,它已經在評論中提到,如果您的瀏覽器支持Web Workers的blobURL,則不需要外部文件。的HTML5Rocks是inspiration我的代碼:

function sample(e) 
{ 
    postMessage(sample_dependency()); 
} 

function sample_dependency() 
{ 
    return "BlobURLs rock!"; 
} 

var blob = new Blob(["onmessage = " + sample + "\n" + sample_dependency]); 
var blobURL = window.URL.createObjectURL(blob); 
var worker = new Worker(blobURL); 

worker.onmessage = function(e) 
{ 
    console.log(e.data); 
}; 

worker.postMessage(""); 

注意事項:

  • 團塊工人將無法成功使用相對URL。 HTML5Rocks鏈接涵蓋了這一點,但它不是原始問題的一部分。

  • 人們已經報告了在網絡工作人員中使用Blob URL的問題。我試過IE11(無論FCU附帶),MS Edge 41.16299(Fall Creator的更新版本),Firefox 57和Chrome 62。沒有提供有關Safari支持的線索。我測試過的那些人已經工作了。

  • 注意的是,在斑點構造函數調用「樣品」和「sample_dependency」引用隱式調用Function.prototype.toString()sample.toString()sample_dependency.toString(),這比調用toString(sample)toString(sample_dependency)很大的不同。

這是因爲它是在搜索如何使用Web Workers而不請求附加文件時出現的第一個stackoverflow。

看了Zevero的回答,他的回購代碼看起來很相似。如果你喜歡乾淨的包裝,這大約是他的代碼所做的。

最後 - 我是一個noob在這裏所以任何/所有的更正讚賞。

相關問題