Service Worker 中的同步或顺序获取

Synchronous or Sequential fetch in Service Worker

我需要从 Service Worker 发送一系列 PUT 和 POST 请求。它们的发送顺序很重要。

要求:

如果我简单地遍历队列并为每个请求调用 fetch,网络变化会(经常)导致请求无序到达服务器。

如何创建一个 fetch 请求链,其中每个结果都取决于前一个请求的成功?


我尝试过的:

Context:我正在使用 "outbox" 个 API 请求来支持离线读取、创建和更新数据。效果很好,除了这个订购问题。

与其立即将队列中的每个请求转换为 Promise,不如在需要时从队列中弹出条目?

var workQueue = [work, goes, here];
var currentItem = workQueue.shift();
return performWorkWith(currentItem)
         .then(handleResponseWithQueue(workQueue));

function handleResponseWithQueue(queue) {
  return function handleResponse(response) {
      if (response.ok && queue.length > 0)
        return performWorkWith(queue.shift()).then(handleResponseWithQueue(queue));
  };
}

您可以将此模式概括为(简化):

function series(work, queue) {
  if (queue.length <= 0) return;
  work(queue.shift()).then(function() {
    if (queue.length > 0) return series(work, queue);
  });
}

我想你会想要关注 Sync loop pattern from that ES6 Promise Patterns 页面。

通过 .reduce() 设置 "success" 承诺链后,您可以在末尾附加一个 .catch() 子句来处理错误报告。承诺链中的任何承诺拒绝/throw 都会使所有 .then() 短路并直接跳到最后的 .catch()

为了使其按照您的描述工作,您需要在 fetch(...).then(...)throw 中明确检查错误 HTTP 响应状态(如果您遇到这种情况),因为 HTTP 错误响应不会触发 .catch()。 (不过,NetworkErrors 或类似的运行时异常 触发 .catch()。)类似于:

fetch('https://example.com').then(response => {
  if (!response.ok) { // See https://fetch.spec.whatwg.org/#ok-status
    throw new Error('Invalid HTTP response: ' + response.status);
  }
  // Otherwise, do something with the valid response.
})