Chrome:`fetch`请求时间过长

4

更新:

我将API从fetch改为XMLHttpRequest,但问题仍然存在。

根据控制台日志,延迟出现在“readyState 1”(即OPENED)和“readyState 2”(即HEADERS_RECEIVED)之间。

另外,也许值得一提的是,在Firefox中它可以正常工作。


我希望能够获得一些指针,以便调试为什么Chrome中对 fetch() 的调用需要 1 秒。

根据“网络”选项卡,请求只花费了12毫秒。然而,在我的日志和“时间轴”选项卡中,fetch() 需要 1.06 秒。(请参见下面的屏幕截图)。

有没有什么技巧可以找出是什么导致了 fetch() 的停顿?

网络选项卡截图: enter image description here

时间轴选项卡截图: enter image description here


第二个截图属于哪个标签页? - Abhijeet
@robertklep 是的,我已经尝试了禁用所有扩展,但仍然看到问题。我尝试查看about:net-internals,就我所知它看起来很好。我开始认为这不是网络问题,而是与promises有关,因为我在很大程度上使用它们。 - user6307701
如果我理解时间轴正确的话,在获取数据的同时确实有一个动画正在运行。也许是某些东西占用了事件循环? - robertklep
JavaScript中只有1个客户端线程,因此任何其他阻塞线程的操作都会导致延迟。将操作移动到WebWorker中,延迟就会消失,因为没有其他东西会在该线程上异步执行。但是,延迟可能会转移到等待来自WebWorker的响应上。 :) - TylerY86
1
我很乐意为您提供答案,但是您需要提供一个可运行的示例作为基础 - 没有上下文,示例可能毫无意义。 - TylerY86
显示剩余13条评论
2个回答

5

我猜测,当你使用async: false时,延迟消失是由于某些东西阻塞了主线程。

在这里,我使用WebWorker内的Fetch进行简单请求,并将结果发送回主线程,大约需要10毫秒。

var workerBlobs = Array.prototype.map.call(document.querySelectorAll("script[type=\"text\/js-worker\"]"), function (oScript) { return new Blob([oScript.textContent], {type: "text/javascript"}); });

var workers = workerBlobs.map(function(oBlob) { return new Worker(URL.createObjectURL(oBlob)); });

var log = document.getElementById('log');

function println(s) {
  log.appendChild(document.createTextNode(s+'\n'));
}
workers[0].onmessage = function(oEvent) {
 println("Done in " + ( performance.now() - start ).toFixed(4) + "ms" );
  println(oEvent.data.message);
}
workers[0].onerror = function(oEvent) {
  println("Error: "+JSON.stringify(oEvent.data));
}

var start = performance.now();
workers[0].postMessage('http://stacksnippets.net/');
#log {
  white-space: pre-wrap;
}
<script type="text/js-worker">
onmessage = function (oEvent) {
  fetch(oEvent.data).then(function(response) {
    response.text().then(function(text){
      console.log("response:",text);
      postMessage({ type: 'response', message: text });
    });
  }).catch(function(err) {
    console.error("error:",err);
    postMessage({ type: 'error', message: err.toString(), stack: err.stack });
  });
}
</script>
<pre id="log"></pre>

在尝试执行时,您需要忽略错误消息;请求在该片段沙盒中有所限制。如果我找到一个可用的URL,我会添加进去。请使用jsfiddle.net示例。

编辑:更新jsfiddle.net示例。 使用postMessage会产生一些轻微的延迟惩罚(在此示例中,在chrome浏览器中约为5ms)。总平均时间仍为10ms。这可能可以通过使用可传输的数组缓冲区和其他技巧来解决。

更明确地说,您应该能够使用此示例在工作线程上执行获取和计时,然后查看它返回到主线程需要多长时间。如果从工作线程到主线程需要太长时间,则某些内容正在阻塞主JS线程。然后您必须寻找并引入一些异步流以允许插入您的获取等操作。


0

我认为在那个错误中没有人说它是一个错误,只是你无法在Chrome 54中重现它。你确定这不是你改变的东西吗?jan.boes...@gmail.com评论说它没有被修复,你的问题是不同的。 - TylerY86
没有,我什么都没改。完全相同的代码适用于Safari、Firefox和Chrome 54,但在Chrome 53中失败了。 - user6307701

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接