馴服定時器和線程
前言
在javascript中,定時器是一個經常被誤用且不被眾人所知的特性,但如果在複雜應用程序中正確應用定時器的話,就會給開發人員帶來非常多的好處。
1 概念
1.1 線程概述
1.js運作在瀏覽器中,是單線程的,即js代碼始終在一個線程上執行,這個線程稱為js引擎線程。
2.瀏覽器是多線程的,除了js引擎線程,它還有
這些線程的作用:
單線程的含義是js只能在一個線程上運行,也就說,js同時只能執行一個js任務,其它的任務則會排隊等待執行。
js是單線程的,並不代表js引擎線程只有一個。js引擎有多個線程,一個主線程,其它的後台配合主線程。
多線程之間會共享運行資源,瀏覽器端的js會操作dom,多個線程必然會帶來同步的問題,所有js核心選擇了單線程來避免處理這個麻煩。js可以操作dom,影響渲染,所以js引擎線程和UI線程是互斥的。這也就解釋了js執行時會阻塞頁面的渲染。
JavaScript運行時,除了一個運行線程,引擎還提供一個消息隊列,裡面是各種需要當前程序處理的消息。新的消息進入隊列的時候,會自動排在隊列的尾端。
1.2 定時器概述
我們說的定時器可以在JavaScript中使用,但我們沒說它是JavaScript自身的一個功能—定時器不是JavaScript的一項功能,定時器作為對象和方法的一部分,才能在瀏覽器中使用。
2 原理
下面我們通過一張圖片來線程中的定時器工作原理
上面這張圖出自《js忍者秘籍1》,本胖這裡借用一下哈
這張圖有很多信息需要消化,但完全理解以後就會對js的非同步執行工作有一個更加深入的理解。
這張圖的X軸是以毫秒為單位的時間軸矩形快的大小意味著js代碼的執行部分以及執行時間。下面本胖就以時刻為單位來簡單明了地說清楚這張圖的內涵哈。
在0ms時刻
在6ms時刻
在18ms時刻
在20ms時刻
第28ms時刻
第30ms時刻
第35ms時刻
第40ms時刻
第42ms時刻
上面分析了0ms-42ms這42ms間發生的事情,可以得出如下的結論
3 API
上面這張圖是定時器的api集合,這裡需要強調一點
無論是window.setTimeout還是window.setInterval,在使用函數名作為調用句柄時都不能帶參數,而在許多場合必須要帶參數,這就需要想方法解決。
3.1 使用字元串傳參
3.2 返回新函數
3.3 修改setTimeout
其實吧,上面的方法都是可以不用的,因為setTimeout默認就是執行第三個參數的(這一點是本胖做分享的時候同事提出來的,非常感謝),直接想下面這樣就可以傳入參數
4 應用
任何知識只有在用實際開發中才有存在的意義,定時器也一樣。下面我們來看看定時器有哪些用處。
4.1 動畫
上圖是之前做活動的一個彈幕效果,當時用的就是定時器。
之所以採用這段代碼來說明定時器做動效的例子,是因為當你用定時器做動效的時候,有一點需要特別注意那就是當app被切換到後台或者瀏覽器tab切換後再次到動效頁面,這時候間隔時間內所有定時器的實例都將同時執行,會造成下面這樣的情況(這裡數據少,不是很明顯)
所以這裡面用了visibilitychange事件,來做一個判斷,誰讓瀏覽器太機智了哈。
4.2 節流+防抖
節流和防抖這對好兄弟很容易被人混淆,這裡做一個說明哈。
節流
防抖
下面用定時器來分別實現簡單的節流和防抖。
節流
防抖
4.3 處理昂貴的計算
在處理一些數據量很多的操作時候(尤其是大量dom操作的時候),會發現瀏覽器會變的很慢,比如下面的這段代碼,目的就是想頁面動態插入500000個tr節點。
其實我們可以巧用定時器的作用
5 總結
上面說了這麼多,從概念到原理到api最後到應用,讓我們一次又一次地被定時器這個神器的東西所嘆服,其實吧定時器是個神奇的東西,有很多意想不到的功能等著我們去探索
(本文完)


TAG:React |