【问题标题】:catching exception thrown by service worker message event捕获服务工作者消息事件引发的异常
【发布时间】:2022-07-09 18:10:50
【问题描述】:

我无法捕获服务工作者的消息事件引发的异常..

客户端使用以下代码在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);
    });

在 SW (sw.js) 方面,我有以下代码:

self.addEventListener("message", async (event) => {
  if (requestType === "SYNC") {
    event.ports[0].postMessage(await longRunningTask());
  }
});

只要软件没有抛出任何异常,这个解决方案就可以正常工作。这意味着客户端在 SW 上长时间运行的进程执行后打印“done”消息。 如果抛出异常,则永远不会返回任何内容。

我已通过以下方式解决了这个问题:

self.addEventListener("message", async (event) => {
  if (requestType === "SYNC") {
    try {
      event.ports[0].postMessage(await longRunningTask());
    } catch (error) {
      event.ports[0].postMessage(error);
    }
  }
});

在这种情况下 - 无论打印“done”,结果总是返回,但是:

  1. 我实际上如何从 Service Worker 中产生异常,以便客户端可以捕获并处理它
  2. 一般来说,如果我正在做的是一种适当的方法来了解如何从客户端调用 SW 上的异步代码,那将是很好的选择...

【问题讨论】:

标签: javascript service-worker workbox service-worker-events


【解决方案1】:

这是我自己最终使用的解决方案:

在服务工作者方面 - 辅助方法:

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 });
    }
  }
}

当异常被捕获时,我们设置错误属性。用作:

self.addEventListener("message", async (event) => {
  const requestType = event?.data?.type;
  if (requestType === "QUEUE_CLEAR") {
    await replyToSenderAsync(event, async () => await clearQueueAsync());
  }
});

在客户端请求包装器上:

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);
    }
  });
}

这里的神奇之处在于读取错误属性并在这种情况下拒绝承诺(因此会引发异常)。用作

try {
    let response = await sendMessageToSWAsync(registration?.active, "QUEUE_GET_ALL");
}
catch(error) {

}

sendMessageToSWAsync(registration?.active, "QUEUE_GET_ALL")
    .then((response) => {})
    .catch((error) => {})

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-04
    • 2012-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多