4

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

要求:

  • 给定请求方法、url 和 JSON 正文,发送请求
  • 如果成功(response.status < 300):
    • 将 body 传递给成功函数
    • 调用队列中的下一个请求
  • 如果失败:
    • 将 responseText 或 err 传递给错误函数
    • 停止执行

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

如何提出一系列fetch请求,其中每个结果都取决于前一个结果的成功?


我试过的:

  • XHR 代替(假设我可以使用“async:false”,但这在 Service Worker 中是不允许的)。
  • setTimeout(sendRequest, i*200). 一个黑客,不可靠。
  • Promise loops基于这些示例ES6 Promise Patterns。这似乎是最有希望的,但这些示例是针对假设成功的简单案例。无法让它与 fetch 一起使用。

上下文:我正在使用 API 请求的“发件箱”来支持离线读取、创建和更新数据。效果很好,除了这个排序问题。

4

2 回答 2

3

我想你会想要遵循ES6 Promise Patterns页面中的Sync 循环模式。

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

为了使其如您所描述的那样工作,您需要明确检查您的错误 HTTP 响应状态fetch(...).then(...)throw如果您遇到一个,因为 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.
})
于 2015-09-08T14:49:18.123 回答
3

与其立即将队列中的每个请求都变成 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);
  });
}
于 2015-09-08T14:43:41.590 回答