使用讓 JavaScript 安全且并發(fā)的 Web Workers
Web Workers 提供了一種在瀏覽器單線程執(zhí)行外運(yùn)行 JS 代碼的方式。單線程處理了包括頁(yè)面內(nèi)容展示,通過(guò)鍵盤(pán)、鼠標(biāo)點(diǎn)擊和其他裝置的用戶交互,以及對(duì)于 AJAX 請(qǐng)求響應(yīng)的一些請(qǐng)求。
事件處理和 AJAX 請(qǐng)求是異步發(fā)生的,可以作為一種通用瀏覽器展示代碼路徑之外的運(yùn)行代碼的方式,但是它們?nèi)匀辉谶@一單線程內(nèi)運(yùn)行,并且必須很快完成。
否則,瀏覽器中的交互會(huì)失去作用。
Web Workers 允許在一個(gè)單獨(dú)的線程運(yùn)行 JS 代碼,完全獨(dú)立于瀏覽器線程及其常規(guī)活動(dòng)。
近年來(lái),關(guān)于 Web Workers 有什么用的問(wèn)題有許多爭(zhēng)論。現(xiàn)如今 CPU 的速度非常快,幾乎每個(gè)人的個(gè)人電腦剛買(mǎi)來(lái)打開(kāi)就擁有幾個(gè) G 的內(nèi)存。類似地,移動(dòng)設(shè)備也已經(jīng)達(dá)到了臺(tái)式機(jī)的處理器速度和內(nèi)存大小。
那些或許曾經(jīng)被認(rèn)為是“計(jì)算密集型”的應(yīng)用程序現(xiàn)在被認(rèn)為沒(méi)那么糟糕了。
所謂的 這不是一片空白 是什么意思?
但是很多次當(dāng)我們決定如何高效地執(zhí)行代碼時(shí),在開(kāi)發(fā)環(huán)境中測(cè)試,我們只考慮了一個(gè)應(yīng)用程序的執(zhí)行。在現(xiàn)實(shí)生活系統(tǒng)中,一個(gè)用戶的手中會(huì)同時(shí)執(zhí)行許多程序。
所以單獨(dú)運(yùn)行的應(yīng)用或許沒(méi)有必要使用 worker 線程,對(duì)于大范圍的用戶來(lái)說(shuō),或許才有必要使用 worker 線程提供最好的體驗(yàn)。
啟動(dòng)一個(gè)新的 worker 就像是規(guī)定一個(gè)包含了 JS 代碼的文件一樣簡(jiǎn)單:
new Worker(‘worker-script.js’)
一旦創(chuàng)建了 worker ,它便獨(dú)立于主瀏覽器線程單獨(dú)運(yùn)行,并執(zhí)行腳本中賦予它的任何代碼。只是瀏覽器看上去和存放專門(mén)腳本文件的 HTML 頁(yè)面是有關(guān)聯(lián)的。
數(shù)據(jù)是通過(guò) JS 代碼中兩個(gè)互補(bǔ)的特性實(shí)現(xiàn)在 Workers 和主 Javascript 線程中的傳遞的:
發(fā)送端的 postMessage() 方法
接收端的 “message” 事件處理器
message 事件處理器像其他的處理器一樣,接收到一個(gè)事件參數(shù),這個(gè)事件有一個(gè) “data” 屬性,擁有從另一端傳來(lái)的數(shù)據(jù)。
這個(gè)可以成為一個(gè)雙向的溝通:在主線程那邊的代碼可以調(diào)用 postMessage() 方法發(fā)送信息到 worker ,然后 worker 可以使用環(huán)境中全局適用的 postMessage() 方法的某種實(shí)現(xiàn)將信息返回給主線程。
在 Web Worker 中的一個(gè)簡(jiǎn)單流程將會(huì)是這樣的:在頁(yè)面的 HTML 中,一條信息發(fā)送到 worker ,然后該頁(yè)面等待一個(gè)響應(yīng):
worker 代碼等待一條信息:
上面的代碼將會(huì)在控制臺(tái)打印輸出:
Message posted from webworker: Worker runningMessage posted from webworker: Worker received data: {“data”:”123456789'}
Worker 期望為長(zhǎng)連接,而無(wú)須反復(fù)重啟
在 Worker 的生命周期里,瀏覽器與 Worker 會(huì)發(fā)送與接收多條消息。
Web Worker 的實(shí)現(xiàn)從以下兩方面確保了線程安全:
為 Worker 線程創(chuàng)建唯一,相互獨(dú)立的全局環(huán)境,而與瀏覽器的相隔離
主從線程調(diào)用 postMessage() 交換的數(shù)據(jù)通過(guò)拷貝進(jìn)行
每一個(gè) Worker 線程的全局環(huán)境都是有別與瀏覽器頁(yè)面的 JavaScript 環(huán)境的,并且是唯一的。Worker 不能訪問(wèn)瀏覽器中的 JavaScript 環(huán)境的任何數(shù)據(jù),連 DOM、windows 對(duì)象、document 對(duì)象都不例外。
Worker 有屬于它們自己版本的東西,像將消息記錄到開(kāi)發(fā)人員的控制臺(tái)的 ‘console’ 對(duì)象,以及發(fā)起 AJAX 請(qǐng)求的 XMLHttpRequest 對(duì)象。但除此之外,在 Worker 中運(yùn)行的 Javascript 代碼應(yīng)該是自包含的;來(lái)自于 Worker 線程的任何輸出,主窗口(main window)希望其都必須通過(guò) postMessage() 函數(shù)作為數(shù)據(jù)返回。
此外,任何數(shù)據(jù)通過(guò) postMessage() 在傳遞之前被復(fù)制(傳遞副本),因此在主窗口線程中修改數(shù)據(jù)并不會(huì)導(dǎo)致 Worker 線程中的數(shù)據(jù)變更。這為 main 線程和 Worker 線程之間傳遞的數(shù)據(jù)的沖突并發(fā)更改提供了固有的保護(hù)。
web workers 用例典型的 web worker 例子就是任何 task 任務(wù)在執(zhí)行過(guò)程中可能會(huì)變得非常昂貴,要么消耗大量的 CPU 時(shí)間,要么花費(fèi)大量的時(shí)鐘時(shí)間(計(jì)算機(jī)調(diào)度的時(shí)鐘)來(lái)訪問(wèn)數(shù)據(jù)。
一些可能會(huì)用到 web workers 的用例:
預(yù)取 和/或 緩存數(shù)據(jù)供后面使用
輪詢和處理來(lái)自web服務(wù)器的數(shù)據(jù)
處理和顯示大數(shù)據(jù)集(think genomics)
與游戲中的動(dòng)作有關(guān)的計(jì)算
圖像處理和過(guò)濾
處理文本數(shù)據(jù)(代碼語(yǔ)法,拼寫(xiě)檢查,字?jǐn)?shù)計(jì)算)
CPU 時(shí)間(片)是一個(gè)簡(jiǎn)單的用例,但是對(duì)資源的網(wǎng)絡(luò)訪問(wèn)也很重要。許多時(shí)候,網(wǎng)絡(luò)上的網(wǎng)絡(luò)通信可以以毫秒為單位執(zhí)行,但有時(shí)網(wǎng)絡(luò)資源變得不可用,直到網(wǎng)絡(luò)恢復(fù)或者請(qǐng)求超時(shí)(需要1-2分鐘才能清除)。
即使一些代碼在開(kāi)發(fā)環(huán)境中被隔離測(cè)試時(shí)可能不會(huì)耗費(fèi)過(guò)長(zhǎng)運(yùn)行時(shí)間,但當(dāng)多個(gè)事物可以同時(shí)運(yùn)行時(shí),它可能會(huì)成為在用戶環(huán)境中運(yùn)行的問(wèn)題。
下面的例子演示了 web workers 可用的兩個(gè)方法。
Demo:游戲碰撞檢測(cè)(注意:這是一個(gè)很長(zhǎng)的例子)
現(xiàn)在基于 HTML5 的游戲在網(wǎng)絡(luò)瀏覽器中隨處可見(jiàn)。游戲的一個(gè)中心方面是游戲環(huán)境中各個(gè)部分之間的計(jì)算運(yùn)動(dòng)和交互。有些游戲的移動(dòng)部分相對(duì)較少,而且很容易將其動(dòng)畫(huà)化( 超級(jí)馬里奧模擬器 ,還有嗎?)。但是讓我們考慮一個(gè)更復(fù)雜的例子。
例子涉及到大量的彩色球在矩形邊界上跳躍(反彈)。目標(biāo)就是讓這些球保持在游戲的邊緣,并且還可以探測(cè)球之間的碰撞并使它們彼此反彈。
邊界檢測(cè)相對(duì)簡(jiǎn)單且執(zhí)行速度快,但是碰撞檢測(cè)在計(jì)算上的要求就更高了,因?yàn)樗笾掳辞虻臄?shù)量的平方數(shù)增長(zhǎng):有“n” 個(gè)球,每一個(gè)球都要和其它球進(jìn)行比較,看它們的路徑是否相交,是否需要被反彈(結(jié)果是 n * n,或者 n 的平方的比較)。
因此有 50 個(gè)球,需要進(jìn)行 2500 次檢查;有 100 個(gè)球,需要進(jìn)行 10000 次檢查(實(shí)際上它略少于這個(gè)數(shù)量的一半:如果你檢查球 n 對(duì)球 m,你不需要稍后檢查球 m 對(duì)球 n,但是,這里面仍然需要大量的計(jì)算)。
來(lái)自:https://www.oschina.net/translate/sing-webworkers-for-safe-concurrent-javascript
相關(guān)文章:
1. python b站視頻下載的五種版本2. Android打包篇:Android Studio將代碼打包成jar包教程3. 實(shí)例代碼講解JAVA多線程4. 基于Go和PHP語(yǔ)言實(shí)現(xiàn)爬樓梯算法的思路詳解5. Xml簡(jiǎn)介_(kāi)動(dòng)力節(jié)點(diǎn)Java學(xué)院整理6. ASP.NET 2.0頁(yè)面框架的幾處變化7. python 爬取豆瓣網(wǎng)頁(yè)的示例8. ASP腳本組件實(shí)現(xiàn)服務(wù)器重啟9. python對(duì)批量WAV音頻進(jìn)行等長(zhǎng)分割的方法實(shí)現(xiàn)10. asp知識(shí)整理筆記4(問(wèn)答模式)
