ホームページ > ウェブフロントエンド > jsチュートリアル > JavaScript のスケジュールされたタスクを実行する方法 (background_javascript のヒント)

JavaScript のスケジュールされたタスクを実行する方法 (background_javascript のヒント)

WBOY
リリース: 2016-05-16 15:24:48
オリジナル
1787 人が閲覧しました

即使忘了 JavaScript 的一切知識,也不會忘記:它是阻塞的。

想像一下,你的瀏覽器裡住著一個魔法小精靈,負責瀏覽器的正常運作。不論渲染 HTML,回應選單指令,螢幕渲染,處理滑鼠點擊,或執行 JavaScript 函數,所有事情都歸一個小精靈處理。它哪忙得過來,一次只能處理一件事情。如果同時丟給它一堆任務,它會列出一個長長的待辦列表,按順序完成它們。

人們常常希望初始化元件和事件處理的 JavaScript 可以盡快執行。可是,有些較不重要的後台任務不會直接影響使用者體驗,例如:

記錄統計

發送資料到社群網路(或新增『分享'按鈕)

預先載入內容

預處理或預先渲染 HTML

他們對時序要求不嚴格,但是為了讓頁面仍然回應,直到使用者捲動頁面或與內容互動時才執行。

選擇之一是 Web Workers ,它可以在獨立的執行緒同時執行程式碼。用於預先載入和預處理再好不過,但你沒有權限直接存取或更新 DOM。你可以在自己的程式碼中避開這一點,但是無法保證第三方腳本例如 Google Analytics 永遠不需要這個。

另一個選擇是setTimeout,例如setTimeout(doSomething, 1);。一旦其它的立即執行任務執行完畢,瀏覽器將執行doSomething()函數。實際上,它被放到了待辦清單的底部。不幸的是,函數將被調用,而不顧處理需求。

#requestIdleCallback

requestIdleCallback 是新API,當瀏覽器稍作喘息的時候,用來執行不太重要的後台排程任務。 難免讓人想起 requestAnimationFrame ,在下次重繪之前,執行函數更新動畫。 想了解更多戳這裡: 使用 requestAnimationFrame 做簡單的動畫 。

requestIdleCallback特性監控:

if ('requestIdleCallback' in window) {
 // requestIdleCallback supported
 requestIdleCallback(backgroundTask);
}
else {
 // no support - do something else
 setTimeout(backgroundTask1, 1);
 setTimeout(backgroundTask2, 1);
 setTimeout(backgroundTask3, 1);
}
ログイン後にコピー

也可以指定配置參數對象,例如 timeout,

requestIdleCallback(backgroundTask, { timeout: 3000; }); 
ログイン後にコピー

確保函數在3秒內調用,不管瀏覽器是否空閒。

deadline物件傳入下列參數時,requestIdleCallback只執行一次回呼:

didTimeout—— 如果可選的 timeout 觸發,則設定為 true
timeRemaining()—— 函數傳回執行任務剩餘的毫秒數
timeRemaining()最多分配50ms用於任務的執行,超過這個限制,也不會停止任務,但是,最好重新呼叫requestIdleCallback安排進一步的處理。

我們來建立一個簡單的例子,讓幾個任務依序執行。任務的函數引用儲存在數組中:

//待执行的函数数组
var task = [
  background1,
  background2,
  background3
];
if ('requestIdleCallback' in window) {
 //支持 requestIdleCallback
 requestIdleCallback(backgroundTask);
}
else {
 //不支持 —— 立刻执行所有任务
 while (task.length) {
  setTimeout(task.shift(), 1);
 }
}
//requestIdleCallback 回调函数
function backgroundTask(deadline) {
 //如果存在,执行下一个任务
 while (deadline.timeRemaining() > 0 && task.length > 0) {
  task.shift()();
 }
 //需要的话,安排进一步任务
 if (task.length > 0) {
  requestIdleCallback(backgroundTask);
 }
}
ログイン後にコピー

#一次 requestIdleCallback 之間不應該做什麼?

Paul Lewis 在 他的文章 中提到,一次 requestIdleCallback 執行的任務應該切成小塊。它不適用於不可預測時間的情況(例如操作 DOM,使用 requestAnimationFrame 回呼會更好)。 resolving(或 rejecting)Promises 時也要謹慎,即使沒有更多的剩餘時間,空閒回調完成之後,回呼函數也會立即執行。

#requestIdleCallback 瀏覽器支援狀況

requestIdleCallback是試驗性特性,規格仍不穩定,碰到 API 變更時不足為奇。 Chrome 47 已支援… 2015年結束前應該可用了。 Opera 應該會跟上。 Microsoft 和 Mozilla 都在考慮 API 是否應該支援 Promises 。 Apple 像往常一樣不鳥。

Paul Lewis(上文提到的)寫了一個簡單的 requestIdleCallback shim ,它可以模擬瀏覽器的空閒監測行為,但不是一個 polyfill( shim 和 polyfill 的區別 )。

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: スケジュールされたタスクを実行する方法

1. GPEDIT.MSC を実行します

2. コンピューターの構成を選択します

--- Windows の設定
セキュリティ設定
—ローカル戦略
—-ユーザー権利の割り当て
右側の [ネットワークからこのコンピュータにアクセス] をダブルクリックします
必要なユーザー名をリストに追加します。

3. --- セキュリティ設定

---安全な選択
サーバー オペレーターによるタスクのスケジュールを許可する
をオンにします

4.-----ローカル戦略

--- バッチ ジョブとしてログイン
必要なユーザー名をリストに追加します。

5.-----ローカル戦略

--- コンピューターとユーザーが委任に対して信頼できるようにします
必要なユーザー名をリストに追加します。
管理者ユーザーになることが最善です。

タスク プランを開始できない場合は、プロンプト コード: 0X80041315

解決策: 2 つの可能性があります。1 つは、システムの「タスク スケジューラ」サービスが開始されていないことです。操作中に「services.msc」と入力して、「タスク スケジューラ」サービスが「すでに完了」に設定されているかどうかを確認できます。 「無効」になっている場合は、それをダブルクリックしてスタートアップの種類を「自動」に変更し、スケジュールされたタスクをリセットすると、実行できるようになります。

現在のアカウントが自動的にログインするように設定されており、そのログイン パスワードが空の場合、XP Professional Edition ではタスク プランが時間通りに実行されない可能性があります。これを行うには、「gpedit.msc」を実行する必要があります。グループ ポリシーを編集します。「コンピューターの構成」→「Windows の設定」→「セキュリティの設定」→「ローカル コンピューター ポリシー」→「セキュリティ オプション」を展開し、右側の「アカウント: パスワードが空のローカル アカウントではコンソール ログインのみを許可します」項目をダブルクリックし、「」を選択します。ポップアップダイアログボックスで「無効です」と表示されます。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート