JavaScript計(jì)劃任務(wù)后臺(tái)運(yùn)行的方法
即使忘了 JavaScript 的一切知識(shí),也不會(huì)忘記:它是阻塞的。
想象一下,你的瀏覽器里住著一個(gè)魔法小精靈,負(fù)責(zé)瀏覽器的正常運(yùn)轉(zhuǎn)。不論渲染 HTML,響應(yīng)菜單命令,屏幕渲染,處理鼠標(biāo)點(diǎn)擊,或者執(zhí)行 JavaScript 函數(shù),所有事情都?xì)w一個(gè)小精靈處理。它哪忙得過來,一次只能處理一件事情。如果同時(shí)丟給它一堆任務(wù),它會(huì)列一個(gè)長(zhǎng)長(zhǎng)的待辦列表,按順序完成它們。
人們常常希望初始化組件和事件處理的 JavaScript 可以盡快被執(zhí)行??墒?,有些不太重要的后臺(tái)任務(wù)不會(huì)直接影響用戶體驗(yàn),比如:
記錄統(tǒng)計(jì)數(shù)據(jù)
發(fā)送數(shù)據(jù)到社交網(wǎng)絡(luò)(或添加‘分享'按鈕)
預(yù)加載內(nèi)容
預(yù)處理或預(yù)渲染 HTML
他們對(duì)時(shí)序要求不嚴(yán)格,但是為了讓頁面仍然響應(yīng),直到用戶滾動(dòng)頁面或者與內(nèi)容交互時(shí)才被執(zhí)行。
選擇之一是 Web Workers ,它可以在獨(dú)立的線程同時(shí)執(zhí)行代碼。用于預(yù)加載和預(yù)處理再好不過,但是你沒有權(quán)限直接訪問或更新 DOM。你可以在自己的代碼中避開這點(diǎn),但是無法保證第三方腳本比如 Google Analytics 永遠(yuǎn)不需要這個(gè)。
另一個(gè)選擇是setTimeout,比如setTimeout(doSomething, 1);。一旦其它的立即執(zhí)行任務(wù)執(zhí)行完畢,瀏覽器將執(zhí)行doSomething()函數(shù)。實(shí)際上,它被放到了待辦列表的底部。不幸的是,函數(shù)將被調(diào)用,而不顧處理需求。
#requestIdleCallback
requestIdleCallback 是新API,當(dāng)瀏覽器稍作喘息的時(shí)候,用來執(zhí)行不太重要的后臺(tái)計(jì)劃任務(wù)。 難免讓人想起 requestAnimationFrame ,在下次重繪之前,執(zhí)行函數(shù)更新動(dòng)畫。 想了解更多戳這里: 使用 requestAnimationFrame 做簡(jiǎn)單的動(dòng)畫 。
requestIdleCallback特性監(jiān)測(cè):
if ('requestIdleCallback' in window) { // requestIdleCallback supported requestIdleCallback(backgroundTask); } else { // no support - do something else setTimeout(backgroundTask1, 1); setTimeout(backgroundTask2, 1); setTimeout(backgroundTask3, 1); }
也可以指定配置參數(shù)對(duì)象,比如 timeout,
requestIdleCallback(backgroundTask, { timeout: 3000; });
確保函數(shù)在3秒之內(nèi)調(diào)用,不管瀏覽器是否空閑。
deadline對(duì)象傳入以下參數(shù)時(shí),requestIdleCallback僅執(zhí)行一次回調(diào):
didTimeout—— 如果可選的 timeout 觸發(fā),則設(shè)置為 true
timeRemaining()—— 函數(shù)返回執(zhí)行任務(wù)剩余的毫秒數(shù)
timeRemaining()最多分配50ms用于任務(wù)的執(zhí)行,超過這個(gè)限制,也不會(huì)停止任務(wù),但是,最好重新調(diào)用requestIdleCallback安排進(jìn)一步的處理。
我們來創(chuàng)建一個(gè)簡(jiǎn)單的例子,讓幾個(gè)任務(wù)按序執(zhí)行。任務(wù)的函數(shù)引用儲(chǔ)存在數(shù)組中:
//待執(zhí)行的函數(shù)數(shù)組 var task = [ background1, background2, background3 ]; if ('requestIdleCallback' in window) { //支持 requestIdleCallback requestIdleCallback(backgroundTask); } else { //不支持 —— 立刻執(zhí)行所有任務(wù) while (task.length) { setTimeout(task.shift(), 1); } } //requestIdleCallback 回調(diào)函數(shù) function backgroundTask(deadline) { //如果存在,執(zhí)行下一個(gè)任務(wù) while (deadline.timeRemaining() > 0 && task.length > 0) { task.shift()(); } //需要的話,安排進(jìn)一步任務(wù) if (task.length > 0) { requestIdleCallback(backgroundTask); } }
#一次 requestIdleCallback 之間不應(yīng)該做什么?
Paul Lewis 在 他的文章 中提到,一次 requestIdleCallback 執(zhí)行的任務(wù)應(yīng)該切成小塊。它不適用于不可預(yù)知時(shí)間的情況(比如操作 DOM,使用 requestAnimationFrame 回調(diào)更好些)。resolving(或者 rejecting)Promises 時(shí)也要謹(jǐn)慎,即使沒有更多的剩余時(shí)間,空閑回調(diào)完成之后,回調(diào)函數(shù)也將立即執(zhí)行。
#requestIdleCallback 瀏覽器支持情況
requestIdleCallback是試驗(yàn)性特性,規(guī)范仍不穩(wěn)定,碰到 API 變更時(shí)不足為奇。Chrome 47 已支持… 2015年結(jié)束前應(yīng)該可用了。Opera 應(yīng)該會(huì)緊跟其后。Microsoft 和 Mozilla 都在考慮 API 是否應(yīng)該支持 Promises 。Apple 像往常一樣不鳥。
Paul Lewis(上文提到的)寫了一個(gè)簡(jiǎn)單的 requestIdleCallback shim ,它可以模擬瀏覽器的空閑監(jiān)測(cè)行為,但不是一個(gè) polyfill( shim 和 polyfill 的區(qū)別 )。
requestIdleCallback shim代碼如下:
/*! * Copyright Google Inc. All rights reserved. * * Licensed under the Apache License, Version . (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-. * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing * permissions and limitations under the License. */ /* * @see https://developers.google.com/web/updates///using-requestidlecallback */ window.requestIdleCallback = window.requestIdleCallback || function (cb) { var start = Date.now(); return setTimeout(function () { cb({ didTimeout: false, timeRemaining: function () { return Math.max(, - (Date.now() - start)); } }); }, ); } window.cancelIdleCallback = window.cancelIdleCallback || function (id) { clearTimeout(id); }
ps: 如何運(yùn)行計(jì)劃任務(wù)
1、運(yùn)行 GPEDIT.MSC
2、選擇計(jì)算機(jī)配置
--- Windows 設(shè)置
--- 安全設(shè)置
--- 本地策略
--- 用戶權(quán)利指派
雙擊右邊的 從網(wǎng)絡(luò)訪問此計(jì)算機(jī)
把需要的用戶名添加到列表。
3、 --- 安全設(shè)置
---安全選擇
開啟允許服務(wù)器操作員計(jì)劃任務(wù)
4、-----本地策略
--- 作為批處理作業(yè)登錄
把需要的用戶名添加到列表。
5、-----本地策略
--- 允許計(jì)算機(jī)和用戶被信任以便于委托
把需要的用戶名添加到列表。
最好是administrator用戶。
如果任務(wù)計(jì)劃無法啟動(dòng),提示代碼:0X80041315
解決方法:這有兩種可能,一是系統(tǒng)中的“Task Scheduler”服務(wù)沒有啟動(dòng),你可在運(yùn)行中鍵入“services.msc”,查看“Task Scheduler”服務(wù)是否被設(shè)置成了“已禁用”,若是,只要雙擊它將啟動(dòng)類型改為“自動(dòng)”,重新設(shè)定一個(gè)計(jì)劃任務(wù)就可以執(zhí)行了。
如果你當(dāng)前賬戶設(shè)置了自動(dòng)登錄,而其登錄密碼又為空,也有可能導(dǎo)致任務(wù)計(jì)劃不能按時(shí)執(zhí)行,在XP專業(yè)版中,需要運(yùn)行“gpedit.msc”來編輯組策略:展開“計(jì)算機(jī)配置→Windows設(shè)置→安全設(shè)置→本地計(jì)算機(jī)策略→安全選項(xiàng)”;雙擊右側(cè)的“賬戶:使用空白密碼的本地賬戶只允許進(jìn)行控制臺(tái)登錄”項(xiàng),在彈出對(duì)話框中選擇“已禁用”。
相關(guān)文章
深入淺析JavaScript字符串操作方法 slice、substr、substring及其IE兼容性
這篇文章主要介紹了JavaScript字符串操作方法 slice、substr、substring及其IE兼容性 的相關(guān)資料,需要的朋友可以參考下2015-12-12JS新標(biāo)簽頁打開的方法大全(讓你的網(wǎng)站訪問更加便捷)
在開發(fā)Web應(yīng)用中我們常常需要在當(dāng)前頁面打開一個(gè)鏈接,但又不希望離開當(dāng)前頁面,這篇文章主要給大家介紹了關(guān)于JS新標(biāo)簽頁打開的方法大全,通過這些方法可以讓你的網(wǎng)站訪問更加便捷,需要的朋友可以參考下2023-10-10JavaScript邏輯運(yùn)算符相關(guān)總結(jié)
這篇文章主要介紹了JavaScript邏輯運(yùn)算符的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)JavaScript,感興趣的朋友可以了解下2020-09-09JavaScript實(shí)現(xiàn)微信號(hào)隨機(jī)切換代碼
這篇文章主要介紹了JavaScript實(shí)現(xiàn)微信號(hào)隨機(jī)切換代碼,需要的朋友可以參考下2018-03-03基于JavaScript如何實(shí)現(xiàn)私有成員的語法特征及私有成員的實(shí)現(xiàn)方式
本文給大家介紹基于JavaScript如何實(shí)現(xiàn)私有成員的語法特征及私有成員的實(shí)現(xiàn)方式,涉及到j(luò)avascript語法特征相關(guān)知識(shí),對(duì)本文感興趣的朋友快來一起學(xué)習(xí)吧2015-10-10一個(gè)用js實(shí)現(xiàn)的頁內(nèi)搜索代碼
一個(gè)用js實(shí)現(xiàn)的頁內(nèi)搜索代碼...2007-05-05