在 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 秒
}
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);
// 延遲工具函式
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(...)
});
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)`,代碼像同步一樣易讀,又不凍結頁面。