导读:本期聚焦于小伙伴创作的《如何用SQLite管理WebNFC标签数据并实现离线读写同步?》,敬请观看详情。把WebNFC采集到的标签信息直接写进本地SQLite数据库,是前端离线应用里很实用的做法。浏览器通过NDEFReader扫描到标签后,若没有本地存储层,刷新页面数据就丢了。SQLite借助sql.js或WA SQLite能在网页内建轻量库,配合IndexedDB持久化文件。本文说明如何设计表结构存标签ID、文本与时间戳,怎样在读写标签时落库,以及网络恢复后把本地记录批量同步到服务端。对比纯localStorage方案,SQLite支持按时间区间和标签类型检索,更适合需要复杂查询的盘点类业务。

在浏览器端直接处理NFC标签数据的场景中,SQLite提供了一种比键值存储更灵活的结构化方案。WebNFC接口允许网页通过NDEFReader对象读取和写入符合NDEF标准的标签,而SQLite可以以WASM形式运行在页面中,将扫描记录持久保存。这种组合特别适合仓储盘点、会议签到等需要离线作业且后续统一上传的系统。

如何用SQLite管理WebNFC标签数据并实现离线读写同步?

WebNFC基础与标签数据模型

WebNFC目前主要在Chrome系浏览器中通过NDEFReader提供能力,它基于Near Field Communication论坛定义的NDEF消息格式。一个NDEF消息可包含多条记录,每条记录有类型、载荷与标识符。常见用法是读取标签中的文本或URL,并在网页中展示或处理。由于每次靠近标签才会触发读取,若不做本地存储,用户离开页面后历史数据无法追溯。

使用SQLite管理这类数据,第一步是设计合理的表结构。我们通常需要保存标签的唯一标识、读取时间、记录类型与解码后的内容。下面给出一种简单的建表语句,利用sql.js在内存或文件化数据库中执行。该结构兼顾了检索效率与扩展能力,后续可按tag_type做分类统计。

CREATE TABLE IF NOT EXISTS nfc_tags (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  tag_id TEXT NOT NULL,
  tag_type TEXT NOT NULL,
  payload TEXT,
  scan_time DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_tag_time ON nfc_tags(scan_time);

上述表中tag_id来自NDEF消息的序列号或自定义标识符,tag_type区分是文本、URI还是自定义MIME。实际项目中,如果标签频繁被同一设备读取,可以再加上设备编号字段以便多端协同。SQLite的索引机制让按时间区间查询变得轻松,这是纯localStorage难以实现的。

在页面中集成SQLite与读写标签

要在网页里跑SQLite,常用方案有sql.js和WebAssembly版官方SQLite。sql.js通过加载wasm文件提供同步API,适合小型库;若数据量大,可采用WA SQLite获得更接近原生的异步接口。初始化时,我们一般把数据库文件存放在IndexedDB,避免每次刷新重新建库。下面的代码展示如何用sql.js载入并插入一条WebNFC读取结果。

import initSqlJs from './sql-wasm.js';
async function setupDB() {
  const SQL = await initSqlJs();
  // 假设已从IndexedDB取得bytes,这里简化为新建
  const db = new SQL.Database();
  db.run('CREATE TABLE IF NOT EXISTS nfc_tags (id INTEGER PRIMARY KEY, tag_id TEXT, payload TEXT, scan_time TEXT)');
  return db;
}
async function saveTag(db, tagId, payload) {
  db.run('INSERT INTO nfc_tags (tag_id, payload, scan_time) VALUES (?, ?, datetime('now'))', [tagId, payload]);
}

读取WebNFC标签时,我们实例化NDEFReader并监听reading事件。在回调里把解码后的文本传给saveTag函数即可落库。需要注意的是,浏览器要求WebNFC必须在用户手势后激活,因此扫描按钮的点击处理中要调用reader.scan()。写入标签也类似,调用write方法前同样需用户确认。

const reader = new NDEFReader();
document.getElementById('scanBtn').addEventListener('click', async () => {
  try {
    await reader.scan();
    reader.addEventListener('reading', event => {
      const tag = event.tag;
      const textRecord = tag.records.find(r => r.recordType === 'text');
      const payload = textRecord ? new TextDecoder().decode(textRecord.data) : '';
      saveTag(db, tag.id || 'unknown', payload);
    });
  } catch (err) {
    console.error('扫描失败', err);
  }
});

这种本地优先的写法让用户即便处于地下仓库等无网环境,也能连续盘点上百个标签而不丢数据。相比直接调接口,SQLite缓冲层显著降低服务端压力,也避免了网络抖动造成的记录丢失。后续只需定时把未同步标记的数据打包上传。

离线数据同步与冲突处理策略

当设备重新联网,就要把SQLite里累积的标签记录提交到中心服务器。简单做法是查询出所有本地新增行,通过fetch批量发送,成功后再打上同步标志。若服务端也允许移动端写标签,就要考虑冲突:同一标签被不同设备修改谁优先。常用方案是最后写入获胜,或按设备号加版本号合并。

下面示例用一条SQL查出自上次同步后的记录,并构造上传数组。我们在表中隐含一个synced字段(可ALTER TABLE添加),初始为0。上传完毕后执行UPDATE置1。这样即便中途失败,重启后仍能续传,不会出现重复提交漏网之鱼。

function getUnsynced(db) {
  const res = db.exec('SELECT id, tag_id, payload, scan_time FROM nfc_tags WHERE synced = 0');
  if (!res.length) return [];
  return res[0].values.map(row => ({id: row[0], tagId: row[1], payload: row[2], time: row[3]}));
}
async function syncToServer(list) {
  const resp = await fetch('https://ipipp.com/api/nfc/sync', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify(list)
  });
  return resp.ok;
}

在冲突规避上,如果业务要求标签状态绝对一致,可改为每次写标签前先从服务端拉取最新值,再在SQLite中更新。但这样牺牲了离线自由度。多数盘点类应用接受短暂不一致,只需在同步时上报全部扫描流水,由后台按时间线还原即可。SQLite的事务特性保证本地插入和标记同步要么都成要么都败,避免半同步态。

整体来看,SQLite加WebNFC的组合用很少的代码量撑起了完整的离线采集闭环。开发者只要留意浏览器兼容性与用户手势限制,就能在巡检、票务等场景快速落地。后续还可将数据库文件导出为文件发给管理员,或用Worker跑SQLite以免阻塞UI,体验会进一步改善。

SQLiteWebNFC标签数据修改时间:2026-08-16 03:14:36

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。