如何让Fetch API承诺尽快解决?

问题描述 投票:0回答:1

TL;DR: 我预计

fetch
API 在发送完整的 HTTP 响应标头后即可解析,但由于某种原因需要 8000 毫秒。

我有一个使用 Express 来响应 HTTP 请求的服务器。它不会给出单一响应,而是随着时间的推移发出多次

write
调用以提供状态更新。在浏览器中,HTTP 请求是使用 fetch API 发出的。响应主体是异步迭代的。

除了一个问题之外,所有这些都工作正常。等待 fetch 调用响应的时间约为 8 秒。我知道服务器发送第一个块不需要8秒。我什至与 XHR 进行了比较,XHR 触发进度事件的时间不到 50 毫秒。我可以做些什么来使初始获取承诺更快地解决吗?

服务器代码

app.post("/bulk-update", (req, res) => {
  buildTask(req.body, 5, (status) => {
    const completed = status.success + status.error;
    const remaining = status.total - completed;

    if (remaining === 0) {
      res.write(`${JSON.stringify(status)}\n`);
      res.end();
      return;
    }

    if (completed % 10 === 0) {
      res.write(`${JSON.stringify(status)}\n`);
    }
  });
});

浏览器代码


let jobStartTime = Date.now();
const response = await fetch(`/bulk-update`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body,
});
console.log("end request", Date.now() - jobStartTime); // <-- this is logging 8000ms

const stream = response.body.pipeThrough(new TextDecoderStream());

let buffer = "";
for await (const chunk of stream) {
  buffer += chunk;

  const lines = buffer.split("\n");
  buffer = lines.at(-1);
  for (let i = 0; i < lines.length - 1; i++) {
    const line = lines[i];
    const status = JSON.parse(line);
    updateProgress(status);
  }

  if (buffer.trim().length > 0) {
    const status = JSON.parse(buffer);
    updateProgress(status);
  }
}
javascript express fetch-api
1个回答
0
投票

通过将服务器响应中的

Content-Type
标头设置为
text/event-stream
,我能够更快地解析提取。看来如果
fetch
没有看到这个标头,解析需要更长的时间。

app.post("/bulk-update", (req, res) => {
  res.setHeader('Content-Type', 'text/event-stream'); // <-- this is the line the fixed it
  res.setHeader('Connection', 'keep-alive'); // Not needed for quick fetch, just is accurate

  buildTask(req.body, 5, (status) => {
    const completed = status.success + status.error;
    const remaining = status.total - completed;

    if (remaining === 0) {
      res.write(`${JSON.stringify(status)}\n`);
      res.end();
      return;
    }

    if (completed % 10 === 0) {
      res.write(`${JSON.stringify(status)}\n`);
    }
  });
});

我在Fetch Standard中没有看到任何关于此的内容。我还在 Chrome 上进行了测试,并且无需标头即可快速解析。据我所知,这是专门针对 Firefox 的实现细节。

© www.soinside.com 2019 - 2024. All rights reserved.