随着 PWA(Progressive Web Apps)的兴起,越来越多的网页应用开始使用 webworker 来加速运行或提高用户体验。但是在 PWA 应用中使用 webworker 常会出现一些问题,这篇文章将会详细介绍这些问题及其解决方法。
问题一: 跨域问题
在 PWA 应用中,由于使用了 Service Worker,因此 webworker 也必须在 Service Worker 中运行。但是如果 webworker 想要访问其他域名的资源,往往会遇到跨域问题。
解决方法:
- 让服务器添加 CORS 头部
在 webworker 中,可以通过 XMLHttpRequest 来请求其他域名的资源。如果服务器在响应中添加了 CORS 头部,浏览器则会认为该服务器允许跨域请求,从而避免跨域问题。
// 在 webworker 中访问其他域名的资源 const xhr = new XMLHttpRequest(); xhr.open('GET', 'https://example.com/data'); xhr.setRequestHeader('Content-Type', 'application/json'); xhr.onload = function() { console.log(xhr.responseText); }; xhr.send();
- 使用 iframe 代理
如果服务器无法添加 CORS 头部,可以尝试使用 iframe 代理的方式访问资源。具体做法是创建一个隐藏的 iframe,并将 iframe 的 src 属性设置为代理页面的 URL。代理页面可以在相同的域名下,并通过 iframe.contentWindow.postMessage() 方法来传递数据。
// 在web worker中通过iframe代理访问其他域名的资源 const iframe = document.createElement('iframe'); iframe.style.display = 'none'; document.body.appendChild(iframe); const proxyUrl = 'https://example.com/proxy?url=' + encodeURIComponent('https://example.com/data'); iframe.src = proxyUrl; window.addEventListener('message', function(event) { if (event.origin !== 'https://example.com') return; console.log(event.data); });
问题二:与 IndexedDB 交互的问题
在 PWA 应用中, IndexedDB 常被用来存储数据。但是在 webworker 中直接访问 IndexedDB 将会报错,因为 IndexedDB 属于浏览器的主线程。因此我们需要查找交互的方法。
解决方法:
- 使用 postMessage 传递消息
在 Service Worker 中可以通过 postMessage 方法来向 webworker 发送消息,同时也可以接收 webworker 发送过来的消息。利用这个机制,我们可以在 Service Worker 中向 IndexedDB 中写入数据,然后通过 postMessage 方法将数据传递给 webworker。
- 利用 Blob 和 Worker
在 Service Worker 中创建一个 Blob 对象,通过 URL.createObjectURL() 方法生成一个 URL,然后将 URL 传递给 webworker 中创建的 Worker 对象,这样 webworker 就可以通过该 URL 访问 Service Worker 中的 Blob 对象,从而与 IndexedDB 交互。
// 在 Service Worker 中发送消息 self.addEventListener('message', function(event) { const db = event.target.result; const tx = db.transaction('store', 'readwrite'); const store = tx.objectStore('store'); const request = store.put({ key: 'value' }); request.onsuccess = function() { const message = { type: 'INSERTED' }; event.ports[0].postMessage(message); }; }); // 在web worker中接收消息 const worker = new Worker('worker.js'); worker.postMessage({ type: 'INSERT' }); worker.onmessage = function(event) { console.log(event.data); };
总结
在 PWA 应用中使用 webworker 可以提高应用的性能和用户体验,但是需要注意跨域问题和与 IndexedDB 的交互问题。本文介绍了解决这些问题的方法,希望对 PWA 开发者有所帮助。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a9e50dadd4f0e0ff35a310