首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

jQuery 迴圈每次暫停 1 秒:用 setTimeout 遞迴替代阻塞睡眠

     編輯:程式設計疑難解答

在 jQuery/JavaScript 中需「迴圈每次執行暫停 1 秒」,**不能用 `while` 迴圈阻塞主執行緒**(會凍結頁面)。正確做法是用 `setTimeout` 遞迴或 `async/await` + `Promise` 實現非阻塞延遲。

錯誤做法:阻塞睡眠 (會凍結瀏覽器)

function sleep(ms) {
    var start = Date.now();
    while (Date.now() - start < ms) { /* 空轉 */ }  // ❌ 阻塞主執行緒
}
for (var i = 0; i < 5; i++) {
    console.log(i);
    sleep(1000);  // 頁面完全無響應 5 秒
}

正確做法一:setTimeout 遞迴 (ES5 相容)

function loopWithDelay(items, callback, delay, index) {
    index = index || 0;
    if (index >= items.length) return;
    callback(items[index], index);
    setTimeout(function() {
        loopWithDelay(items, callback, delay, index + 1);
    }, delay);
}

// 使用
var arr = ['A', 'B', 'C', 'D', 'E'];
loopWithDelay(arr, function(item, idx) {
    console.log('處理:', item, '索引:', idx);
}, 1000);

正確做法二:async/await + Promise (現代、可讀性最佳)

// 延遲工具函式
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));

async function processWithDelay(items, callback) {
    for (const item of items) {
        await callback(item);  // 等待 callback 完成 (若 callback 也是 async)
        await sleep(1000);     // 暫停 1 秒,不阻塞主執行緒
    }
}

// 使用
const items = ['A', 'B', 'C', 'D', 'E'];
processWithDelay(items, async (item) => {
    console.log('處理:', item);
    // 這裡可做 AJAX、DOM 操作等異步任務
    // await $.post(...)
});

正確做法三:jQuery `.queue()` / `.delay()` (針對動畫隊列)

var $div = $('#myDiv');
var items = ['A', 'B', 'C'];
$.each(items, function(i, item) {
    $div.queue(function(next) {
        console.log('處理:', item);
        // 做些事...
        setTimeout(next, 1000);  // 1 秒後執行下一個隊列項
    });
});
// 啟動隊列
$div.dequeue();

關鍵差異對照

方法阻塞主執行緒可處理異步任務適用場景
`while` 睡眠✅ 是 (凍結頁面)❌ 否**絕不使用**
`setTimeout` 遞迴❌ 否✅ 是 (回調中)ES5、簡單邏輯
`async/await` + `sleep`❌ 否✅ 是 (原生)**現代首選**、複雜流程
jQuery `.queue()`❌ 否✅ 是動畫/效果隊列

進階:可取消的延遲迴圈

class DelayedLoop {
    constructor(items, callback, delay) {
        this.items = items;
        this.callback = callback;
        this.delay = delay;
        this.index = 0;
        this.timer = null;
        this.running = false;
    }
    start() {
        this.running = true;
        this.tick();
    }
    stop() {
        this.running = false;
        clearTimeout(this.timer);
    }
    tick() {
        if (!this.running || this.index >= this.items.length) return;
        this.callback(this.items[this.index], this.index);
        this.index++;
        this.timer = setTimeout(() => this.tick(), this.delay);
    }
}

// 使用
var loop = new DelayedLoop(['A','B','C','D'], (item, i) => console.log(item), 1000);
loop.start();
// 5 秒後停止
setTimeout(() => loop.stop(), 5000);

核心原則:**JavaScript 單執行緒,任何迴圈延遲必須用非阻塞方式 (`setTimeout`/`Promise`/`queue`)**。現代專案首選 `async/await` + `sleep(ms)`,代碼像同步一樣易讀,又不凍結頁面。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved