第20章 JavaScript API
1. Atomics 与 SharedArrayBuffer
- SharedArrayBuffer:多个 Worker 共享的二进制缓冲区,避免数据复制。
- Atomics:原子操作(add, sub, and, or, xor, compareExchange, load, store, exchange, wait, notify)。
- 原子等待/通知:
Atomics.wait 和 Atomics.notify 用于线程同步(类似条件变量)。
- 安全头:需要
Cross-Origin-Opener-Policy: same-origin 和 Cross-Origin-Embedder-Policy: require-corp。
2. 跨上下文消息(postMessage)
targetWindow.postMessage(message, targetOrigin, [transfer])。
transfer 是可转移对象列表(如 ArrayBuffer、MessagePort),所有权被转移,原环境不可用。
- 监听
message 事件:event.data, event.origin, event.source。
- 始终校验
event.origin 白名单,防止 XSS。
- 示例:
iframe.contentWindow.postMessage(data, 'https://trusted.com')。
3. Encoding API
- TextEncoder:
new TextEncoder().encode(str) → Uint8Array(UTF-8)。
- TextDecoder:
new TextDecoder('utf-8').decode(buffer),可选 { stream: true } 处理流式数据。
- 其他编码:
TextDecoder 支持 'utf-16le'、'utf-16be'、'iso-8859-2' 等(取决于实现)。
4. File API 与 Blob
- Blob:
new Blob(['Hello'], { type: 'text/plain' })。blob.slice(start, end, type) 切割。
- File:继承 Blob,额外属性
name, lastModified。
- FileReader:异步读取,事件
onload, onerror, onprogress。reader.result 为结果。
- URL.createObjectURL(blob):生成 blob: 链接,需手动
revokeObjectURL 释放内存。
- Blob 转 ArrayBuffer:
await blob.arrayBuffer()。
- Blob 转文本:
await blob.text()(ES2018)。
5. Fetch API
fetch(url, { method, headers, body, credentials, mode, cache, redirect, referrer, integrity, signal })。
credentials:'omit'(不发送凭据)、'same-origin'(同源发送)、'include'(跨域发送)。
- 响应对象属性:
ok(状态码 200-299)、status、statusText、headers、url、redirected。
- 中断请求:
const controller = new AbortController(); fetch(url, { signal: controller.signal }); controller.abort();。
- 自定义超时:
Promise.race([fetch(url, { signal }), timeoutPromise])。
- 流式读取响应:
res.body.getReader() 逐块读取(大文件下载)。
6. Beacon API
navigator.sendBeacon(url, data) 确保数据在页面卸载时发送完成,不阻塞。
- 数据大小建议不超过 64KB。
- 触发:
beforeunload、unload 事件或页面关闭时。
- 替代方案:
fetch 带 keepalive: true(部分浏览器支持)。
7. WebSocket
- 创建:
let ws = new WebSocket('wss://echo.websocket.org')。
- 属性:
readyState(0: CONNECTING, 1: OPEN, 2: CLOSING, 3: CLOSED)、bufferedAmount(未发送字节数)。
- 事件:
onopen, onmessage, onerror, onclose(close 事件有 code, reason)。
- 发送:
ws.send(data),可发送 String、Blob、ArrayBuffer、TypedArray。
- 接收:
event.data 可能是 Blob 或 String,可通过 ws.binaryType = 'arraybuffer' 设为 ArrayBuffer。
- 子协议:
new WebSocket(url, ['protocol1', 'protocol2']),服务器需协商。
- 心跳保活:定时发送 ping 帧(部分服务器支持自动响应)。
8. 拖放 API(Drag and Drop)
- 元素可拖动:
draggable="true"。拖拽时数据存储:dragstart 中 e.dataTransfer.setData('text/plain', data)。
- 放置目标:
dragover 中 e.preventDefault() 允许放置;drop 中 e.dataTransfer.getData('text/plain') 获取数据。
- 拖拽效果:
e.dataTransfer.effectAllowed = 'move'(copy, move, link)。
- 文件拖放:
drop 事件中 e.dataTransfer.files 获取文件列表。
- 自定义拖拽图像:
e.dataTransfer.setDragImage(element, x, y)。
- 拖动类型:
dragstart 中可设置 e.dataTransfer.dropEffect 和 effectAllowed 配合。
9. Notifications API
- 权限请求:
Notification.requestPermission().then(permission => {...})(返回 Promise)。
- 创建通知:
new Notification(title, { body, icon, tag, requireInteraction, silent, data, actions })。
- 事件监听:
notification.onclick, onclose, onerror, onshow。
- 关闭:
notification.close()。
- 持久化通知(Service Worker 中使用):
self.registration.showNotification(title, options)。
10. Page Visibility API
document.visibilityState:'visible', 'hidden'。
- 监听
visibilitychange 事件,优化资源(如暂停视频、停止轮询)。
- 配合
document.hidden(已废弃但兼容好)。
11. Streams API
- ReadableStream:
fetch(url).then(res => res.body) 返回流,调用 getReader() 迭代读取。
- WritableStream:可构建写入流,例如
new WritableStream({ write(chunk) {} })。
- TransformStream:可连接读取流和写入流,进行数据转换。
- 管道:
readable.pipeThrough(transformStream).pipeTo(writable)。
- 示例:逐行处理大文件:
const reader = file.stream().pipeThrough(new TextDecoderStream()).getReader()。
12. Web Workers
12.1 专用 Worker
- 创建:
const worker = new Worker('worker.js')。
- 通信:
worker.postMessage(data, transferList),worker.onmessage = e => {...}。
- 终止:
worker.terminate()(主线程)或 self.close()(Worker 内部)。
- 错误处理:
worker.onerror = err => {...}。
12.2 共享 Worker
- 创建:
const shared = new SharedWorker('shared.js'),通过 shared.port 通信(需 start())。
- 多页面连接会共享同一 Worker 实例。
12.3 Worker 内可用 API
- 子集:
navigator(部分)、XMLHttpRequest、fetch、setTimeout、WebSocket、IndexedDB、postMessage。
- 不可用:
DOM、window、document、localStorage。
13. Service Workers
- 注册:
navigator.serviceWorker.register('/sw.js', { scope: '/' })。返回 Promise。
- 生命周期事件:
install(缓存静态资源)、activate(清理旧缓存)、fetch(拦截请求)、message。
- 安装时缓存:
caches.open(CACHE_NAME).then(cache => cache.addAll(urls))。
- 激活时清理旧缓存:
caches.keys() 删除非当前版本。
fetch 事件响应:event.respondWith(caches.match(event.request).then(response => response || fetch(event.request)))。
- 更新机制:每次注册新脚本都会重新 install,等待旧版本不再使用时激活。
- 跳过等待:
self.skipWaiting();立即控制:clients.claim()。
performance.now():高精度微秒时间戳(相对页面导航开始)。
performance.mark(name):标记时间点;performance.measure(name, startMark, endMark):测量两点间耗时。
performance.getEntriesByType('resource'):获取所有资源加载详情(含 duration, transferSize 等)。
PerformanceObserver:new PerformanceObserver(list => {...}).observe({ entryTypes: ['paint', 'navigation'] })。
- 导航计时:
performance.timing(旧,建议用 PerformanceNavigationTiming)。
15. IndexedDB
- 打开数据库:
let request = indexedDB.open('MyDB', version),监听 onsuccess, onerror, onupgradeneeded。
onupgradeneeded 中创建对象仓库:db.createObjectStore('storeName', { keyPath: 'id' })。
- 事务:
let tx = db.transaction('storeName', 'readwrite'),获取仓库 tx.objectStore('storeName')。
- 增:
store.add(data),改:store.put(data),删:store.delete(key),查:store.get(key)。
- 游标:
store.openCursor().onsuccess = e => { let cursor = e.target.result; if(cursor) {... cursor.continue(); } }。
- 索引:
store.createIndex('nameIndex', 'name', { unique: false }),使用 store.index('nameIndex').get('Alice')。
16. Fullscreen API
- 全屏请求:
element.requestFullscreen() 返回 Promise。
- 退出:
document.exitFullscreen()。
- 事件:
document.addEventListener('fullscreenchange', () => {...})。
- 全屏元素:
document.fullscreenElement(无全屏时为 null)。
- CSS 伪类:
:fullscreen。
17. Screen Orientation API
- 获取方向:
screen.orientation.type(如 'portrait-primary', 'landscape-secondary')。
- 锁定方向:
screen.orientation.lock('landscape').catch(e => {...})(需用户手势触发)。
- 解锁:
screen.orientation.unlock()。
- 监听变化:
screen.orientation.addEventListener('change', () => {...})。
18. Geolocation API
- 单次定位:
navigator.geolocation.getCurrentPosition(success, error, options)。
- 持续定位:
navigator.geolocation.watchPosition(success, error, options) 返回 ID。
- 停止:
navigator.geolocation.clearWatch(watchId)。
options:enableHighAccuracy: true(耗电)、timeout(毫秒)、maximumAge(缓存时间)。
- 成功回调参数
position:coords.latitude, longitude, accuracy, altitude, heading, speed;timestamp。
19. 媒体元素(<audio> 和 <video>)
19.1 基本操作
- 属性:
currentTime(读/写,秒)、duration、paused、ended、muted、volume(0-1)、playbackRate(播放速度)、loop、autoplay、controls。
- 方法:
play() 返回 Promise;pause();load()(重载);canPlayType(type) 检测支持。
19.2 事件
- 加载:
loadstart, durationchange, loadedmetadata, loadeddata, progress。
- 就绪:
canplay, canplaythrough(可无停顿播放)。
- 播放:
play, playing, pause, waiting, seeking, seeked。
- 结束:
ended。
- 状态:
volumechange, ratechange, timeupdate(时间更新时触发,高频)。
- 错误:
error(error.code:1=中止,2=网络,3=解码,4=不支持)。
19.3 高级功能
- Web Audio API:
AudioContext 处理音频流,可与 video 或 audio 结合(createMediaElementSource)。
- 视频轨道:
video.videoTracks、audioTracks、textTracks(字幕)。
- 截图:
canvas.drawImage(video, 0, 0, width, height)。
- 录制:
MediaRecorder API(结合 canvas.captureStream() 或 getUserMedia)。
20. 其他补充 API
20.1 BroadcastChannel
- 创建:
const bc = new BroadcastChannel('channelName')。
- 发送:
bc.postMessage(data)。
- 接收:
bc.onmessage = e => console.log(e.data)。
- 关闭:
bc.close()。
- 同源下不同页面、Worker 均可通信。
20.2 Payment Request API
- 创建支付请求:
new PaymentRequest(paymentMethods, paymentDetails, options)。
- 调用:
request.show() 返回 Promise,用户确认后得到 PaymentResponse。
- 处理支付:
response.complete('success')。
20.3 Credential Management API
- 存储凭据:
navigator.credentials.store(credential)。
- 获取凭据:
navigator.credentials.get({ password: true, federated: true, publicKey: {...} })。
- 防止自动登录:
preventSilentAccess()。
20.4 Web Share API
- 触发分享:
navigator.share({ title, text, url, files }),需用户手势(如点击事件)。
- 检测是否支持:
if (navigator.share) { ... }。
- 必须是 HTTPS。
20.5 Web Locks API
- 请求锁:
navigator.locks.request('resource_name', async lock => { ... })。
- 用于跨标签页/Worker 的并发控制(如 IndexedDB 写入防冲突)。
20.6 Channel Messaging API(MessageChannel)
- 创建管道:
const { port1, port2 } = new MessageChannel()。
- 将
port2 发送给另一个全局(如 iframe、Worker),port1 保留在本地。
- 通信:
port.postMessage(data),port.onmessage = e => {...}。
- 常用于 Worker 间通信或主线程与 iframe 的点对点通信。
21. 小结
- 共享内存 + Atomics 同步,postMessage 跨窗需防伪。
- 文件处理:Blob + FileReader + URL.createObjectURL。
- 网络请求:Fetch 灵活加中断,WebSocket 实时双工,Beacon 上报不阻塞。
- 多线程:Web Worker 算力解放,Service Worker 离线之王。
- 性能计时:now + mark + measure + Observer。
- 存储:IndexedDB 海量事务。
- 体验:全屏、屏幕方向、地理位置、通知、分享。
- 媒体:play/pause/currentTime,监听事件。
22. 常见面试题速查
- SharedArrayBuffer 为什么需要 COOP/COEP 头? → 防止 Spectre 漏洞。
- postMessage 的 transferList 有什么用? → 零拷贝转移对象所有权,提高性能。
- Fetch 如何实现请求超时? →
Promise.race([fetch, new Promise((_, reject) => setTimeout(() => reject('timeout'), ms))])。
- WebSocket 的 readyState 有哪些值? → 0 连接中,1 已打开,2 关闭中,3 已关闭。
- Service Worker 中如何确保新版本立即生效? →
self.skipWaiting() + clients.claim()。
- PerformanceObserver 可以观察哪些条目? →
'paint'(FP/FCP)、'largest-contentful-paint'、'layout-shift'、'first-input'、'navigation'、'resource'。
- IndexedDB 中游标的作用? → 遍历多条数据,可以修改或删除当前项。
- 如何实现无用户交互的视频自动播放? → 目前不可行,但可以静音(
muted 属性)后自动播放。
- Web Audio API 与
<audio> 如何结合? → const source = audioContext.createMediaElementSource(audioElement),可连接滤波器等。
- BroadcastChannel 与 postMessage 的区别? → BroadcastChannel 是一对多广播,不返回源信息;postMessage 是一对一,可以指定目标 origin。
posted @
2024-05-08 17:31
Li_pk
阅读(
6)
评论()
收藏
举报