我們將模擬一個任務調度器,使用者可以排隊執行不同的任務,每個任務將使用回呼函數來模擬它們完成的時間。當任務完成後,會呼叫指定的回呼函數來執行相應的動作。
我們首先創建一個基本的 HTML 框架,包含新增任務的輸入框、執行按鈕和顯示結果的區域。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>回呼函數範例</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
padding: 20px;
}
#taskList {
margin-top: 20px;
list-style: none;
padding: 0;
}
.task {
padding: 10px;
border: 1px solid #ddd;
margin-bottom: 5px;
}
button {
padding: 5px 10px;
font-size: 1rem;
}
</style>
</head>
<body>
<h1>回呼函數應用</h1>
<label for="taskInput">任務名稱:</label>
<input type="text" id="taskInput" placeholder="任務名稱">
<label for="timeInput">執行時間(秒):</label>
<input type="number" id="timeInput" placeholder="秒數">
<button id="addTaskBtn">新增任務</button>
<button id="executeBtn">執行任務</button>
<ul id="taskList"></ul>
<div id="result"></div>
<script src="callbackApp.js"></script>
</body>
</html>
接下來,我們編寫 JavaScript,來實現新增任務、執行任務以及回呼函數的邏輯。
let taskInput = document.getElementById('taskInput');
let timeInput = document.getElementById('timeInput');
let addTaskBtn = document.getElementById('addTaskBtn');
let executeBtn = document.getElementById('executeBtn');
let taskList = document.getElementById('taskList');
let result = document.getElementById('result');
let tasks = [];
// 新增任務
addTaskBtn.addEventListener('click', () => {
let taskName = taskInput.value.trim();
let taskTime = parseInt(timeInput.value);
if (taskName === '' || isNaN(taskTime) || taskTime <= 0) {
alert('請輸入有效的任務名稱與時間');
return;
}
tasks.push({ name: taskName, time: taskTime });
let taskItem = document.createElement('li');
taskItem.classList.add('task');
taskItem.textContent = `任務:${taskName},耗時:${taskTime} 秒`;
taskList.appendChild(taskItem);
taskInput.value = '';
timeInput.value = '';
});
// 執行任務(使用回呼函數)
executeBtn.addEventListener('click', () => {
if (tasks.length === 0) {
alert('沒有任務可執行');
return;
}
result.textContent = '開始執行任務...';
executeTasks(tasks, () => {
result.textContent = '所有任務已完成!';
});
});
// 執行任務的函數,使用回呼函數來處理完成後的動作
function executeTasks(taskQueue, callback) {
if (taskQueue.length === 0) {
callback(); // 當所有任務執行完畢後,呼叫回呼函數
return;
}
let currentTask = taskQueue.shift(); // 取出第一個任務
result.textContent = `正在執行:${currentTask.name}`;
setTimeout(() => {
result.textContent = `${currentTask.name} 完成!`;
executeTasks(taskQueue, callback); // 遞迴調用,執行下一個任務
}, currentTask.time * 1000); // 模擬任務的執行時間
}
新增任務:
taskInput
和 timeInput
取得任務名稱和執行時間,並將它們新增到 tasks
陣列中。執行任務:
setTimeout
)。executeTasks()
再次執行下一個任務,直到所有任務完成後執行回呼函數。回呼函數:
executeTasks()
函數中的回呼函數是為了在所有任務執行結束後觸發「所有任務已完成」的訊息。非同步操作:
setTimeout
來模擬非同步任務的耗時操作,這也是常見的回呼函數使用情境,例如處理非同步 API 請求。進度顯示:可以顯示剩餘的任務數量或進度條,讓使用者更直觀地了解任務執行進度。
錯誤處理:可以加入錯誤回呼函數,模擬在執行任務時發生的錯誤處理流程。
setTimeout
是模擬非同步操作的好方法,讓你熟悉如何管理執行流程。shift()
來取出任務並執行,並在每次任務完成後遞迴呼叫下一個任務。