现代浏览器已经是一个具备操作系统能力的平台。 从多线程计算到硬件连接,从本地文件系统到身份支付——掌握这些 API 能让 Web 应用跳出「页面」的局限,提供接近原生的体验。
一、多线程:Web Workers
1.1 Dedicated Worker(专用)
// worker.js
self.onmessage = (event) => {
const { data, type } = event.data;
if (type === 'heavy-computation') {
const result = fibonacci(data);
self.postMessage({ type: 'result', value: result });
}
};
function fibonacci(n) {
return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}
// main.js
const worker = new Worker('/worker.js');
worker.postMessage({ type: 'heavy-computation', data: 40 });
worker.onmessage = (event) => {
console.log('Result:', event.data.value); // 102334155
worker.terminate();
};
// 用 Comlink 简化通信
import * as Comlink from 'comlink';
const api = Comlink.wrap(new Worker('/worker.js'));
const result = await api.heavyComputation(40);
1.2 Shared Worker(共享)
多个标签页共享同一个 Worker:
// shared-worker.js
const connections = [];
self.onconnect = (event) => {
const port = event.ports[0];
connections.push(port);
port.onmessage = (e) => {
// 广播给所有连接
connections.forEach(conn => {
if (conn !== port) conn.postMessage(e.data);
});
};
port.start();
};
二、客户端存储
2.1 存储方案对比
| API | 容量 | 持久性 | 结构化查询 | 适用场景 |
|---|---|---|---|---|
| localStorage | ~5-10MB | 持久 | 无 | 简单键值(token、theme) |
| sessionStorage | ~5-10MB | 标签页 | 无 | 临时状态(表单草稿) |
| IndexedDB | 硬盘 50%+ | 持久 | Indexed | 大量结构化数据、离线应用 |
| Cache API | 硬盘 50%+ | 持久 | 无(按 Request) | Service Worker 缓存 |
| Origin Private File System | 用户授权 | 持久 | 无 | 本地文件读写 |
2.2 IndexedDB 封装
// idb.ts(基于 idb 库封装)
import { openDB, DBSchema } from 'idb';
interface MyDB extends DBSchema {
documents: {
key: string;
value: {
id: string;
title: string;
content: string;
updatedAt: number;
};
indexes: { 'by-date': number };
};
}
const db = await openDB<MyDB>('my-app', 1, {
upgrade(db) {
const store = db.createObjectStore('documents', { keyPath: 'id' });
store.createIndex('by-date', 'updatedAt');
}
});
// 写入
await db.put('documents', { id: 'doc-1', title: 'Hello', content: '...', updatedAt: Date.now() });
// 读取
const doc = await db.get('documents', 'doc-1');
// 查询索引
const recent = await db.getAllFromIndex('documents', 'by-date', IDBKeyRange.lowerBound(Date.now() - 86400000));
2.3 Storage API:持久化与配额
// 请求持久化存储(不会被浏览器自动清除)
if (navigator.storage && navigator.storage.persist) {
const isPersistent = await navigator.storage.persist();
console.log('Persistent storage:', isPersistent);
}
// 查看配额
const estimate = await navigator.storage.estimate();
console.log('Usage:', estimate.usage);
console.log('Quota:', estimate.quota);
// 清理
await caches.keys().then(names => Promise.all(names.map(n => caches.delete(n))));
三、布局观测 API
3.1 Intersection Observer(元素可见性)
// 无限滚动 / 懒加载
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
loadMoreData();
// 可选:观察一次后停止
// observer.unobserve(entry.target);
}
});
}, {
root: null, // 视口
rootMargin: '100px', // 提前触发
threshold: 0.1 // 10% 可见时触发
});
observer.observe(document.querySelector('.load-more-trigger'));
3.2 Resize Observer(元素尺寸变化)
const ro = new ResizeObserver((entries) => {
for (const entry of entries) {
const { width, height } = entry.contentRect;
console.log(`${entry.target.tagName}: ${width}x${height}`);
}
});
ro.observe(document.querySelector('.chart-container'));
3.3 Mutation Observer(DOM 变化)
const mo = new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (mutation.type === 'childList') {
console.log('Nodes added:', mutation.addedNodes.length);
}
}
});
mo.observe(document.body, { childList: true, subtree: true });
四、数据交互 API
4.1 Clipboard API
// 写入剪贴板(需用户交互触发)
async function copyToClipboard(text) {
try {
await navigator.clipboard.writeText(text);
showToast('已复制');
} catch (err) {
console.error('Copy failed:', err);
}
}
// 读取剪贴板
async function readFromClipboard() {
const text = await navigator.clipboard.readText();
return text;
}
// 复制富文本
async function copyRichText(html) {
const blob = new Blob([html], { type: 'text/html' });
const item = new ClipboardItem({ 'text/html': blob });
await navigator.clipboard.write([item]);
}
4.2 File System Access API
// 打开文件选择器
async function openFile() {
const [fileHandle] = await window.showOpenFilePicker({
types: [{
description: 'Images',
accept: { 'image/*': ['.png', '.jpg', '.avif'] }
}],
multiple: false
});
const file = await fileHandle.getFile();
const content = await file.text(); // 或 file.arrayBuffer()
return content;
}
// 保存文件
async function saveFile(content) {
const handle = await window.showSaveFilePicker({
suggestedName: 'document.md',
types: [{ accept: { 'text/markdown': ['.md'] } }]
});
const writable = await handle.createWritable();
await writable.write(content);
await writable.close();
}
4.3 Web Share
async function shareContent() {
if (navigator.share) {
await navigator.share({
title: 'My Awesome Article',
text: 'Check out this article about frontend engineering',
url: 'https://example.com/article'
});
} else {
// fallback: 复制链接
await navigator.clipboard.writeText('https://example.com/article');
}
}
五、硬件连接 API
| API | 支持 | 场景 |
|---|---|---|
| Web Bluetooth | Chrome, Edge | 连接 BLE 设备(心率带、打印机) |
| Web USB | Chrome, Edge | 连接 USB 设备(Arduino、扫描仪) |
| Web Serial | Chrome, Edge | 串口通信(工业设备、3D 打印机) |
| Web NFC | Chrome Android | NFC 标签读写 |
| Web HID | Chrome, Edge | HID 设备(游戏手柄、条码枪) |
// Web Bluetooth 示例:连接心率带
async function connectHeartRate() {
const device = await navigator.bluetooth.requestDevice({
filters: [{ services: ['heart_rate'] }]
});
const server = await device.gatt.connect();
const service = await server.getPrimaryService('heart_rate');
const characteristic = await service.getCharacteristic('heart_rate_measurement');
characteristic.addEventListener('characteristicvaluechanged', (event) => {
const value = event.target.value.getUint8(1);
console.log('Heart rate:', value);
});
await characteristic.startNotifications();
}
六、多媒体 API
6.1 Web Speech API
// 语音识别
const recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
recognition.lang = 'zh-CN';
recognition.continuous = true;
recognition.onresult = (event) => {
const transcript = event.results[event.results.length - 1][0].transcript;
console.log('Speech:', transcript);
};
recognition.start();
// 语音合成
const utterance = new SpeechSynthesisUtterance('你好,世界');
utterance.lang = 'zh-CN';
utterance.rate = 1.0;
speechSynthesis.speak(utterance);
6.2 MediaRecorder
const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
const recorder = new MediaRecorder(stream);
const chunks = [];
recorder.ondataavailable = (e) => chunks.push(e.data);
recorder.onstop = () => {
const blob = new Blob(chunks, { type: 'video/webm' });
const url = URL.createObjectURL(blob);
// 上传或下载
};
recorder.start();
// ...
recorder.stop();
七、身份与支付
7.1 Credential Management API
// 保存密码
await navigator.credentials.store(new PasswordCredential({
id: 'user@example.com',
password: 'password123',
name: 'John Doe'
}));
// 自动登录
const cred = await navigator.credentials.get({ password: true });
if (cred) {
await login(cred.id, cred.password);
}
// WebAuthn / Passkey
const credential = await navigator.credentials.create({
publicKey: {
challenge: Uint8Array.from('random-challenge', c => c.charCodeAt(0)),
rp: { name: 'My App', id: 'example.com' },
user: { id: Uint8Array.from('user-id'), name: 'user', displayName: 'User' },
pubKeyCredParams: [{ alg: -7, type: 'public-key' }]
}
});
7.2 Payment Request API
const paymentMethods = [{
supportedMethods: 'https://apple.com/apple-pay',
data: { version: 3, merchantIdentifier: 'merchant.example' }
}];
const details = {
total: { label: 'Total', amount: { value: '99.99', currency: 'CNY' } },
displayItems: [
{ label: 'Product', amount: { value: '99.99', currency: 'CNY' } }
]
};
const request = new PaymentRequest(paymentMethods, details);
const response = await request.show();
await response.complete('success');
八、页面通信与报告
8.1 BroadcastChannel
// 跨同源标签页通信
const channel = new BroadcastChannel('app_channel');
// 发送
channel.postMessage({ type: 'login', user: { id: 'u1' } });
// 接收
channel.onmessage = (event) => {
if (event.data.type === 'login') {
console.log('User logged in another tab:', event.data.user);
}
};
8.2 Beacon API
// 可靠发送数据(页面卸载时也能发送)
window.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden') {
const data = JSON.stringify({
page: location.href,
duration: Date.now() - pageStartTime,
events: eventBuffer
});
navigator.sendBeacon('/analytics', data);
}
});
8.3 Reporting API
// 自动上报 CSP 违规、Deprecation 警告、Crash
// Report-To: {"group":"default","max_age":86400,"endpoints":[{"url":"https://example.com/reports"}]}
// 也可以用 ReportingObserver 在 JS 中捕获
const observer = new ReportingObserver((reports) => {
for (const report of reports) {
console.log('Report:', report.type, report.body);
// { type: 'csp-violation', body: { ... } }
}
}, { buffered: true });
observer.observe();
九、能力地图速查
| 类别 | API | 支持度 | 场景 |
|---|---|---|---|
| 多线程 | Web Workers | ~100% | 大数据计算 |
| 存储 | IndexedDB | ~100% | 离线数据 |
| 观测 | Intersection Observer | ~98% | 懒加载 |
| 社交 | Web Share | ~85% | 原生分享 |
| 文件 | File System Access | ~70% (Chromium) | 本地文件编辑 |
| 硬件 | Web Bluetooth | ~70% (Chromium) | IoT |
| 语音 | Web Speech | ~90% | 语音输入 |
| 身份 | WebAuthn / Passkey | ~90% | 无密码登录 |
| 支付 | Payment Request | ~60% | 原生支付 |
| 通信 | BroadcastChannel | ~95% | 多标签同步 |
参考与延伸阅读
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。