JavaScript高级程序设计笔记 20

第20章 JavaScript API

1. Atomics 与 SharedArrayBuffer

  • SharedArrayBuffer:多个 Worker 共享的二进制缓冲区,避免数据复制。
  • Atomics:原子操作(add, sub, and, or, xor, compareExchange, load, store, exchange, wait, notify)。
  • 原子等待/通知:Atomics.waitAtomics.notify 用于线程同步(类似条件变量)。
  • 安全头:需要 Cross-Origin-Opener-Policy: same-originCross-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

  • TextEncodernew TextEncoder().encode(str) → Uint8Array(UTF-8)。
  • TextDecodernew TextDecoder('utf-8').decode(buffer),可选 { stream: true } 处理流式数据。
  • 其他编码:TextDecoder 支持 'utf-16le''utf-16be''iso-8859-2' 等(取决于实现)。

4. File API 与 Blob

  • Blobnew Blob(['Hello'], { type: 'text/plain' })blob.slice(start, end, type) 切割。
  • File:继承 Blob,额外属性 name, lastModified
  • FileReader:异步读取,事件 onload, onerror, onprogressreader.result 为结果。
  • URL.createObjectURL(blob):生成 blob: 链接,需手动 revokeObjectURL 释放内存。
  • Blob 转 ArrayBufferawait 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)、statusstatusTextheadersurlredirected
  • 中断请求: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。
  • 触发:beforeunloadunload 事件或页面关闭时。
  • 替代方案:fetchkeepalive: true(部分浏览器支持)。

7. WebSocket

  • 创建:let ws = new WebSocket('wss://echo.websocket.org')
  • 属性:readyState(0: CONNECTING, 1: OPEN, 2: CLOSING, 3: CLOSED)、bufferedAmount(未发送字节数)。
  • 事件:onopen, onmessage, onerror, oncloseclose 事件有 code, reason)。
  • 发送:ws.send(data),可发送 StringBlobArrayBufferTypedArray
  • 接收:event.data 可能是 BlobString,可通过 ws.binaryType = 'arraybuffer' 设为 ArrayBuffer
  • 子协议:new WebSocket(url, ['protocol1', 'protocol2']),服务器需协商。
  • 心跳保活:定时发送 ping 帧(部分服务器支持自动响应)。

8. 拖放 API(Drag and Drop)

  • 元素可拖动:draggable="true"。拖拽时数据存储:dragstarte.dataTransfer.setData('text/plain', data)
  • 放置目标:dragovere.preventDefault() 允许放置;drope.dataTransfer.getData('text/plain') 获取数据。
  • 拖拽效果:e.dataTransfer.effectAllowed = 'move'(copy, move, link)。
  • 文件拖放:drop 事件中 e.dataTransfer.files 获取文件列表。
  • 自定义拖拽图像:e.dataTransfer.setDragImage(element, x, y)
  • 拖动类型:dragstart 中可设置 e.dataTransfer.dropEffecteffectAllowed 配合。

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

  • ReadableStreamfetch(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(部分)、XMLHttpRequestfetchsetTimeoutWebSocketIndexedDBpostMessage
  • 不可用:DOMwindowdocumentlocalStorage

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()

14. Performance API

  • performance.now():高精度微秒时间戳(相对页面导航开始)。
  • performance.mark(name):标记时间点;performance.measure(name, startMark, endMark):测量两点间耗时。
  • performance.getEntriesByType('resource'):获取所有资源加载详情(含 duration, transferSize 等)。
  • PerformanceObservernew 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)
  • optionsenableHighAccuracy: true(耗电)、timeout(毫秒)、maximumAge(缓存时间)。
  • 成功回调参数 positioncoords.latitude, longitude, accuracy, altitude, heading, speedtimestamp

19. 媒体元素(<audio><video>

19.1 基本操作

  • 属性:currentTime(读/写,秒)、durationpausedendedmutedvolume(0-1)、playbackRate(播放速度)、loopautoplaycontrols
  • 方法: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(时间更新时触发,高频)。
  • 错误:errorerror.code:1=中止,2=网络,3=解码,4=不支持)。

19.3 高级功能

  • Web Audio APIAudioContext 处理音频流,可与 videoaudio 结合(createMediaElementSource)。
  • 视频轨道video.videoTracksaudioTrackstextTracks(字幕)。
  • 截图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. 常见面试题速查

  1. SharedArrayBuffer 为什么需要 COOP/COEP 头? → 防止 Spectre 漏洞。
  2. postMessage 的 transferList 有什么用? → 零拷贝转移对象所有权,提高性能。
  3. Fetch 如何实现请求超时?Promise.race([fetch, new Promise((_, reject) => setTimeout(() => reject('timeout'), ms))])
  4. WebSocket 的 readyState 有哪些值? → 0 连接中,1 已打开,2 关闭中,3 已关闭。
  5. Service Worker 中如何确保新版本立即生效?self.skipWaiting() + clients.claim()
  6. PerformanceObserver 可以观察哪些条目?'paint'(FP/FCP)、'largest-contentful-paint''layout-shift''first-input''navigation''resource'
  7. IndexedDB 中游标的作用? → 遍历多条数据,可以修改或删除当前项。
  8. 如何实现无用户交互的视频自动播放? → 目前不可行,但可以静音(muted 属性)后自动播放。
  9. Web Audio API 与 <audio> 如何结合?const source = audioContext.createMediaElementSource(audioElement),可连接滤波器等。
  10. BroadcastChannel 与 postMessage 的区别? → BroadcastChannel 是一对多广播,不返回源信息;postMessage 是一对一,可以指定目标 origin。
posted @ 2024-05-08 17:31  Li_pk  阅读(6)  评论(0)    收藏  举报