在Vue應用程序中使用Web Workers
這篇文章假定您具有Javascript和Vue的基本知識。
單線程JavaScript
作為單線程編程語言,Javascript一次只能執(zhí)行一組指令,這意味著在執(zhí)行下一個進程之前,所有其他進程都必須等待一條指令完成。
如果我們必須執(zhí)行繁重的進程,并且還希望用戶仍然能夠與我們的應用程序交互,那么這將在我們的Web應用程序中帶來速度問題。比如說我們需要計算多個投資包的投資回報率,仍然要保證這些進程是非阻塞的,不在主線程上運行,這樣我們就可以在主線程上執(zhí)行其他任務,比如進行網(wǎng)絡請求......進入web workers。
注意:阻塞是指串行處理,一次執(zhí)行一項操作。另一方面,非阻塞代碼(異步)可以并行運行(或多線程)
Web Worker允許我們在后臺線程中運行進程,并在這些進程完成時通知主線程。這大大提升了性能,因為我們不需要把主線上的所有東西都分塊。
Web workers
Web Workers是Web內(nèi)容在后臺線程中運行腳本的一種簡單方法,可以在不干擾用戶界面的情況下執(zhí)行任務。一旦創(chuàng)建,worker就可以通過向代碼指定的事件處理程序發(fā)布消息,向創(chuàng)建它的JavaScript代碼發(fā)送消息(反之亦然)。
Javascript中的Web workers
主線程使用“Worker”構(gòu)造函數(shù)創(chuàng)建 Worker,該構(gòu)造函數(shù)只接收一個參數(shù),即Worker文件的路徑。Worker包含將在Worker線程中運行的代碼;Worker在另一個不同于當前 window 的全局上下文中運行。
數(shù)據(jù)通過消息(message)在worker和主線程之間傳遞——主線程和worker線程使用 postMessage() 方法發(fā)送消息,并使用 onmessage 處理程序響應發(fā)送的消息。
這是一個使用Javascript實現(xiàn)Web workers的簡單示例:
MartinsOnuoha/js-webworker-example「鏈接」
在Vue中使用Web Worker
要在Vue應用中使用web worker,我們可以使用vue的web worker包裝器,比如vue-worker包,或者在低層實現(xiàn)它(從底層開始構(gòu)建)。我將保持它的簡單性,并將在不使用vue-worker包的情況下構(gòu)建這個示例,這樣我們就可以了解底層發(fā)生了什么。
讓我們設(shè)置我們的vue應用程序。
為了保持簡單,我將在純HTML頁面中使用Vue CDN,而不是使用Vue-CLI生成項目。讓我們設(shè)置應用程序文件夾。我們的文件夾結(jié)構(gòu)如下所示:
應用
我們將在Vue中實現(xiàn)同樣的Javascript例子(一個倒計時計時器),由于倒計時計時器是一個長期運行的過程,我們將把它委托給我們的web worker,并在我們的主線程上觸發(fā)一個方法,當我們的計數(shù)器值被10整除時,從這個API中獲取一個隨機的狗圖像。結(jié)果看起來像這樣:
https://silent-wish.surge.sh/
HTML
在index.html文件中,我們將構(gòu)建我們的標記,包括vue-next CDN鏈接,我們的主腳本文件,以及vue的掛載點。
在這里,我們在頂部導入了CSS文件,在底部導入了腳本。我們還會顯示來自數(shù)據(jù)對象的counter屬性,當它可用時。使用image標簽,我們還會在可用時渲染“dogImage”值。
接下來,我們將在app.js條目文件中設(shè)置vue應用。
因為這個示例應用程序嚴重依賴于web Worker,所以我們需要首先檢查瀏覽器是否支持Worker,然后再實例化一個新的Worker類。
接下來,我們設(shè)置App對象。
- const App = {
- ...
- }
我們將有兩個 data 屬性:
- const App = {
- data() {
- return {
- dogImage: null,
- counter: 0,
- }
- }
- }
在我們的method對象中,我們將創(chuàng)建一個方法來從dog API中獲取隨機狗圖像。
- methods: {
- getDogImage () {
- fetch('https://dog.ceo/api/breeds/image/random')
- .then((response) => response.json())
- .then((data) => {
- this.dogImage = data.message
- })
- }
- }
最后,在 mounted 的鉤子中,我們將第一次調(diào)用 getDogImage 方法,然后在我們的worker對象上設(shè)置一個 onmessage 監(jiān)聽器來監(jiān)聽worker線程的更新,我們檢查worker發(fā)送的計數(shù)器值是否被10整除,如果是,我們再次調(diào)用 getDogImage 方法。
- ...
- mounted () {
- this.getDogImage()
- worker.onmessage = (e) => {
- this.counter = e.data
- if (this.counter % 10 === 0) {
- this.getDogImage()
- }
- }
- },
- ...
然后,我們將App對象掛載在 #app 元素上。
整個app.js文件應如下所示:
為了美觀起見,我們將添加一些樣式。將其添加到app.css文件中。
您可以在VScode上使用LiveServer啟動應用程序。
源碼
查看所用示例應用程序的源代碼:https://github.com/MartinsOnuoha/vue-webworker-example