JavaScript中用IndexedDB缓存在线考试答题卡的核心是:创建examDB数据库和answerSheets对象存储,以studentId为主键、examId为索引,实现增删查改;页面加载时优先读取缓存,卸载前自动保存,提交后及时清理。

在 JavaScript 中用 IndexedDB 缓存在线考试答题卡的临时数据,核心是:创建数据库、设计对象存储、增删查改答题记录,并在页面卸载前自动保存,在加载时优先读取缓存。关键在于结构清晰、操作可靠、避免阻塞主线程。
1. 初始化考试专用数据库和答题卡对象存储
首次打开考试页时,打开或创建名为 examDB 的数据库,版本设为 1;定义一个叫 answerSheets 的对象存储空间,以考生 ID(如 studentId)为主键,支持按考试 ID(examId)查询:
const DB_NAME = 'examDB';
const STORE_NAME = 'answerSheets';
let db;
function initDB() {
return new Promise((resolve, reject) => {
const request = indexedDB.open(DB_NAME, 1);
request.onupgradeneeded = (event) => {
db = event.target.result;
if (!db.objectStoreNames.contains(STORE_NAME)) {
// 主键为 studentId,启用 autoIncrement 仅用于兜底(实际不用)
const store = db.createObjectStore(STORE_NAME, { keyPath: 'studentId' });
// 创建二级索引,方便按 examId 查所有该考试的答题卡
store.createIndex('byExamId', 'examId', { unique: false });
}
};
request.onsuccess = () => {
db = request.result;
resolve(db);
};
request.onerror = () => reject(request.error);
});
}
2. 保存/更新当前答题卡(自动覆盖同用户同考试)
每次用户切换题、点击选项、输入文字后,调用保存逻辑。使用 put() 自动插入或更新——只要 studentId 和 examId 相同,就覆盖旧数据:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
async function saveAnswerSheet(sheet) {
if (!db) await initDB();
return new Promise((resolve, reject) => {
const tx = db.transaction(STORE_NAME, 'readwrite');
const store = tx.objectStore(STORE_NAME);
const request = store.put(sheet); // sheet 必须含 studentId 字段
request.onsuccess = () => resolve();
request.onerror = () => reject(request.error);
});
}
// 示例调用:
saveAnswerSheet({
studentId: 'S1001',
examId: 'EXAM20240501',
answers: { q1: 'A', q2: 'true', q3: '手动输入内容...' },
timestamp: Date.now()
});
3. 加载缓存答题卡(页面初始化时优先读取)
进入考试页时,立即尝试从 IndexedDB 加载对应用户的最新答题卡。推荐用索引查 examId + studentId 组合,确保精准:
立即学习“Java免费学习笔记(深入)”;
async function loadAnswerSheet(studentId, examId) {
if (!db) await initDB();
return new Promise((resolve, reject) => {
const tx = db.transaction(STORE_NAME, 'readonly');
const store = tx.objectStore(STORE_NAME);
const index = store.index('byExamId');
// 先按 examId 查出所有匹配项,再过滤 studentId(因索引不唯一)
const request = index.getAll(IDBKeyRange.only(examId));
request.onsuccess = () => {
const sheets = request.result.filter(s => s.studentId === studentId);
resolve(sheets.length ? sheets[0] : null);
};
request.onerror = () => reject(request.error);
});
}
// 页面加载后调用:
loadAnswerSheet('S1001', 'EXAM20240501').then(sheet => {
if (sheet) {
restoreUI(sheet.answers); // 把 answers 数据还原到题目组件
}
});
4. 安全清理与生命周期配合
答题提交成功后,应主动删除缓存;用户退出考试页(非刷新)时也建议清除,避免残留。同时监听 beforeunload 做最后保存(但注意:该事件中不能用 async/await,需同步写):
- 提交后调用
deleteAnswerSheet(studentId, examId)(用delete()方法) - 页面卸载前触发一次同步保存:
window.addEventListener('beforeunload', () => saveAnswerSheetSync(...))(封装成不返回 Promise 的同步版本) - 考试超时或主动交卷时,清空当前考试的所有缓存(可扩展支持多场考试并行)

















