前言
PWA (Progressive Web App) 技术是一种可以让 Web 应用具备类似原生应用的用户体验的技术,同时也可以实现离线缓存和推送通知等功能。在 PWA 应用中,上传图片是一个常见的功能,但是如果采用同步的方式进行上传,用户体验会非常差,所以我们需要使用异步上传来提升用户体验。本文将介绍 PWA 技术实现异步上传图片的方法。
技术实现
在 PWA 中上传图片有两种方式:一种是通过 Web API 进行上传,另一种则是通过 Service Worker 进行上传。虽然两者的实现方法不同,但是都可以实现异步上传。
Web API 实现异步上传
在 PWA 中,可以通过 Web API 的 XMLHttpRequest
对象来实现异步上传。代码如下:
// javascriptcn.com 代码示例 function uploadImage(file) { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open('POST', '/api/upload'); xhr.onreadystatechange = () => { if (xhr.readyState === 4 && xhr.status === 200) { resolve(xhr.responseText); } else if (xhr.readyState === 4 && xhr.status !== 200) { reject(xhr.statusText); } }; xhr.send(file); }); } const fileInput = document.querySelector('input[type=file]'); fileInput.addEventListener('change', () => { const file = fileInput.files[0]; uploadImage(file).then((response) => { console.log(response); }).catch((error) => { console.error(error); }); });
在上面的代码中,我们通过 XMLHttpRequest
对象发送一个 POST 请求,将文件内容发送到服务器端进行处理,然后通过 Promise 对象处理异步上传的结果。当上传成功时,将返回服务器端返回的数据;当上传失败时,将返回错误信息。
Service Worker 实现异步上传
在 PWA 中,也可以通过 Service Worker 的 Fetch API 来实现异步上传。代码如下:
// javascriptcn.com 代码示例 self.addEventListener('fetch', (event) => { const url = new URL(event.request.url); if (url.pathname === '/api/upload') { event.respondWith(uploadImage(event.request)); } }); function uploadImage(request) { return new Promise((resolve, reject) => { fetch(request.clone()).then((response) => { return response.arrayBuffer(); }).then((buffer) => { self.clients.matchAll({ type: 'window' }).then((clients) => { clients.forEach((client) => { client.postMessage({ type: 'upload', buffer }); }); }); resolve(new Response('Upload success.')); }).catch((error) => { reject(error); }); }); } self.addEventListener('message', (event) => { if (event.data.type === 'get-upload-message') { self.clients.matchAll({ type: 'window' }).then((clients) => { clients.forEach((client) => { client.postMessage({ type: 'upload-message' }); }); }); } });
在上面的代码中,我们通过 Service Worker 的 Fetch API 拦截了上传图片的请求,并将请求转发给服务器端进行处理。当服务器端返回成功时,我们将处理结果打包成 Fetch API 的 Response 对象并返回给客户端。同时,我们也将上传结果通过 postMessage()
方法通知到客户端。
在客户端中,我们可以通过 navigator.serviceWorker.controller
访问 Service Worker,并监听 message
事件来获取上传结果。代码如下:
// javascriptcn.com 代码示例 const fileInput = document.querySelector('input[type=file]'); const btnUpload = document.querySelector('button[data-action=upload]'); const progress = document.querySelector('.progress'); btnUpload.addEventListener('click', () => { if (navigator.serviceWorker.controller) { const file = fileInput.files[0]; const body = new FormData(); body.append('file', file); const request = new Request('/api/upload', { method: 'POST', body }); fetch(request).then((response) => { return response.text(); }).then((text) => { console.log(text); navigator.serviceWorker.controller.postMessage({ type: 'get-upload-message' }); }).catch((error) => { console.error(error); }); } }); navigator.serviceWorker.addEventListener('message', (event) => { if (event.data.type === 'upload') { const buffer = event.data.buffer; const messageChannel = new MessageChannel(); messageChannel.port1.addEventListener('message', (event) => { const { uploaded, total } = event.data; progress.value = uploaded / total * 100; }); navigator.serviceWorker.controller.postMessage({ type: 'get-upload-message' }, [messageChannel.port2]); const view = new Uint8Array(buffer); const blob = new Blob([view], { type: 'image/jpeg' }); const img = document.createElement('img'); img.src = URL.createObjectURL(blob); document.querySelector('.preview').appendChild(img); } else if (event.data.type === 'upload-message') { const messageChannel = event.ports[0]; const uploaded = progress.value; const total = progress.max; messageChannel.postMessage({ uploaded, total }); } });
在上面的代码中,我们先通过 fetch()
函数拦截了上传图片的请求,并将请求转发给 Service Worker 进行处理。当服务器端返回成功时,我们通过 postMessage()
方法通知 Service Worker 获取上传结果。同时,我们也监听了 Service Worker 的 message
事件,当 Service Worker 发送结果时,我们将结果显示在客户端界面上。
总结
本文介绍了 PWA 技术实现异步上传图片的方法,其中通过 Web API 和 Service Worker 两种方式都可以实现异步上传。通过以上的示例代码,相信读者已经掌握了 PWA 技术实现异步上传图片的方法,可以在实际项目中应用并实现更好的用户体验。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/653e62217d4982a6eb7e2f65