簡體   English   中英

在 Javascript 中執行后台任務

[英]Execute Background Task In Javascript

我有一個需要在客戶端上運行的 CPU 密集型任務。 理想情況下,我希望能夠調用 function 並使用 jquery 觸發進度事件,以便更新 UI。

我知道 javascript 不支持線程,但我看到一些有前途的文章試圖使用 setTimeout 模擬線程。

為此使用的最佳方法是什么? 謝謝。

基本上,您要做的是將操作分成幾部分。 因此,假設您要處理10 000個項目,將它們存儲在列表中,然后在每次調用之間稍加延遲處理少量項目。 這是一個你可以使用的簡單結構:

function performTask(items, numToProcess, processItem) {
    var pos = 0;
    // This is run once for every numToProcess items.
    function iteration() {
        // Calculate last position.
        var j = Math.min(pos + numToProcess, items.length);
        // Start at current position and loop to last position.
        for (var i = pos; i < j; i++) {
            processItem(items, i);
        }
        // Increment current position.
        pos += numToProcess;
        // Only continue if there are more items to process.
        if (pos < items.length)
            setTimeout(iteration, 10); // Wait 10 ms to let the UI update.
    }
    iteration();
}

performTask(
    // A set of items.
    ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'],
    // Process two items every iteration.
    2,
    // Function that will do stuff to the items. Called once for every item. Gets
    // the array with items and the index of the current item (to prevent copying
    // values around which is unnecessary.)
    function (items, index) {
        // Do stuff with items[index]
        // This could also be inline in iteration for better performance.
    });

另請注意, Google Gears支持在單獨的線程上執行操作 Firefox 3.5還引入了自己的工作人員來做同樣的事情 (盡管他們遵循W3標准 ,而Google Gears使用自己的方法。)

我最近有一個類似的問題要解決,我需要保持我的UI線程自由,同時處理一些數據顯示。

我寫了一個庫Background.js來處理幾個場景:順序后台隊列(基於WorkerQueue庫),每個定時器調用每個定時器的作業列表,以及幫助將你的工作分解成更小塊的數組迭代器。 這里的示例和代碼: https//github.com/kmalakoff/background

請享用!

如果您可以強制使用瀏覽器,或者您已經知道它是Firefox的新版本,則可以使用Mozilla的新WebWorkers 它允許您生成新線程。

根據您的要求,您可以使用Gears輕松下車。 Gears支持線程,可以做你想要的。

如前所述,setTimeout是另一種選擇。 根據您的任務類型,您可以將循環的每次迭代切換到單獨的setTimeout調用,其間有一些間距,或者您可能需要將主算法的各個部分分成單獨的函數,這些函數可以逐個調用與您調用每次迭代的方式相同。

凱文很棒! 幾年前我寫了類似的東西,雖然不太復雜。 如果有人想要,源代碼在這里:

http://www.leapbeyond.com/ric/jsUtils/TaskQueue.js

任何帶有run()方法的東西都可以作為任務排隊。 任務可以重新排隊以執行塊中的工作。 您可以優先處理任務,隨意添加/刪除它們,暫停/恢復整個隊列等。適用於異步操作 - 我最初的用途是管理多個並發XMLHttpRequests。

基本用法非常簡單:

var taskQueue = new TaskQueue();
taskQueue.schedule("alert('hello there')");

.js文件中的標題注釋提供了更高級的示例。

這是我對問題的解決方案,以防有人想要簡單的可復制粘貼代碼:

    var iterate = function (from, to, action, complete) {
        var i = from;
        var impl = function () {
            action(i);
            i++;
            if (i < to) setTimeout(impl, 1);
            else complete();
        };
        impl();
    };

我最強烈的建議是在操作期間顯示一個簡單的loading.gif。 如果用戶“被告知”可能需要一些時間,用戶通常會接受一段時間。

Ajaxload - Ajax加載gif生成器

這是如何在JavaScript中創建線程的一個非常基本的示例。 請注意,由您決定是否中斷線程函數(yeld指令)。 如果需要,可以使用setTimeout而不是while循環來定期運行調度程序。 另請注意,此示例僅適用於JavaScript版本1.7+(firefox 3+),您可以在此處嘗試: http//jslibs.googlecode.com/svn/trunk/jseval.html

//// thread definition
function Thread( name ) {

    for ( var i = 0; i < 5; i++ ) {

        Print(i+' ('+name+')');
        yield;
    }
}

//// thread management
var threads = [];

// thread creation
threads.push( new Thread('foo') );
threads.push( new Thread('bar') );

// scheduler
while (threads.length) {

    var thread = threads.shift();
    try {
        thread.next();
        threads.push(thread);
    } catch(ex if ex instanceof StopIteration) { }
}

輸出是:

0 (foo) 0 (bar) 1 (foo) 1 (bar) 2 (foo) 2 (bar) 3 (foo) 3 (bar) 4 (foo) 4 (bar) 

使用requestIdleCallback()

然后您將使用瀏覽器的空閑時間來處理您的任務。

示例位於: https://developer.mozilla.org/en-US/docs/Web/API/Background_Tasks_API

有一個功能(我寫的時候是實驗性的):

https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestIdleCallback

似乎不是真正的多線程,而是執行比其他(UI)任務優先級低的任務

所以解決方案可以是:

  1. 讓你的任務異步
  2. 使用此 requestIdleCallback 開始您的任務
  3. 在你的任務中使用帶有微時間的 setTimeout() 循環,比如在一些主循環和他的內部邏輯之間

用戶界面可以在這些超時中頻繁更新

似乎這個問題已經在節點本身解決了。
需要child_process,它包含在nodejs 0.10.4中

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM