No puedo detectar una excepción lanzada por el evento de mensaje del trabajador del servicio.
El cliente usa el siguiente código para ejecutar el comando en el SW:
import { messageSW } from "workbox-window"; // .. code for Workbox initialization/registration omitted messageSW(registration?.active, { type: "SYNC" }) .then((results) => { console.log("done"); }) .catch((e) => { console.error(e); }); En el lado SW ( sw.js ) tengo el siguiente código:
self.addEventListener("message", async (event) => { if (requestType === "SYNC") { event.ports[0].postMessage(await longRunningTask()); } });Esta solución funciona bien siempre que el software no genere ninguna excepción. Lo que significa que el cliente imprime el mensaje " hecho " después de que se ejecuta el proceso de ejecución prolongada en el SW. Si se lanza la excepción, nunca se devuelve nada.
He logrado solucionar el problema haciendo lo siguiente:
self.addEventListener("message", async (event) => { if (requestType === "SYNC") { try { event.ports[0].postMessage(await longRunningTask()); } catch (error) { event.ports[0].postMessage(error); } } });En este caso, el resultado siempre se devuelve independientemente, se imprime " hecho ", pero:
Aquí está mi propia solución que terminé usando:
en el lado del trabajador de servicio - método auxiliar:
async function replyToSenderAsync(event, task) { let isCanReply = event.ports && event.ports.length >= 0; try { const result = await task(); if (isCanReply) { event.ports[0].postMessage({ error: null, message: result }); } } catch (error) { if (isCanReply) { event.ports[0].postMessage({ error: error, message: null }); } } }Cuando se detecta una excepción, establecemos la propiedad de error. Usar como:
self.addEventListener("message", async (event) => { const requestType = event?.data?.type; if (requestType === "QUEUE_CLEAR") { await replyToSenderAsync(event, async () => await clearQueueAsync()); } });en el contenedor de solicitud del lado del cliente:
function sendMessageToSWAsync(targetSW, messageType, message) { return new Promise(function (resolve, reject) { if ( !isServiceWorkerSupported.value || !isServiceWorkerRegistered.value || !targetSW ) { reject(new Error("Unable to send the message to a service worker")); } try { messageSW(targetSW, { type: messageType, message: message }) .then((messageResponse) => { if (!messageResponse) { reject(new Error("Service worker responsed with empty response")); } else { if (messageResponse.error) { reject(messageResponse.error); } else { resolve(messageResponse.message); } } }) .catch((messageError) => { reject(messageError); }); } catch (error) { reject(error); } }); }La magia aquí es leer la propiedad de error y rechazar la promesa si ese es el caso. (lo que provoca que se lance una excepción. Usar como
try { let response = await sendMessageToSWAsync(registration?.active, "QUEUE_GET_ALL"); } catch(error) { } sendMessageToSWAsync(registration?.active, "QUEUE_GET_ALL") .then((response) => {}) .catch((error) => {})