【问题标题】:XHR OnLoad Promise blocking other OnLoad callbacksXHR OnLoad Promise 阻止其他 OnLoad 回调
【发布时间】:2015-06-02 10:16:20
【问题描述】:

我正在尝试从我的服务器下载文件,然后在加载的数据上运行 Promises。 我的问题是,我的 Promise 似乎出于某种原因阻止了一切:

它开始下载所有文件,一旦第一个文件被下载,它会阻止其他文件下载并运行它的“onLoad”回调完整的承诺链,然后继续下载剩余的文件。新文件完成后,它会阻止其他下载并运行承诺链等等。

我的 onload 回调包含以下内容:

function(response) {

  window.console.log('on load callback...');

      var sequence = Promise.resolve();
      sequence
      .then(function(){
        sleep(10000);
        window.console.log('sleep 1 is over...');
        return 'DONE!';
      })
      .then(function(){
        sleep(10000);
        window.console.log('sleep 2 is over...');
        return 'DONE!';
      })
      .then(function(){
        sleep(10000);
        window.console.log('sleep 3 is over...');
        return 'DONE!';
      });
}

我的睡眠功能如下:

 function sleep(milliseconds) {
   var start = new Date().getTime();
   for (var i = 0; i < 1e7; i++) {
     if ((new Date().getTime() - start) > milliseconds){
       break;
    }
  }
 }

在控制台中返回:

on load callback...
sleep 1 is over...
sleep 2 is over...
sleep 3 is over...
on load callback...
sleep 1 is over...
sleep 2 is over...
sleep 3 is over...
on load callback...
sleep 1 is over...
sleep 2 is over...
sleep 3 is over...
on load callback...
sleep 1 is over...
sleep 2 is over...
sleep 3 is over...

任何帮助将不胜感激。

我可以理解当“睡眠”运行时下载被阻止,但我不明白为什么它会在继续下载之前运行所有“睡眠 1”、“睡眠 2”和“睡眠 3”剩余文件。

==== 编辑 ====

我使用“承诺”的 XMLHttpRequest 和 Promise.all() 加载文件。 (http://www.html5rocks.com/en/tutorials/es6/promises/)

最好, 尼古拉斯

【问题讨论】:

  • 下载对应的代码在哪里?
  • 我在 EDITS 中添加了信息。根本没有魔法,我使用了一个“承诺的”XMLHttpRequest,为每个文件构建我的序列数组,然后可以 Promise.all()。

标签: javascript asynchronous xmlhttprequest es6-promise


【解决方案1】:

我认为您在这里要问的是(使用这个可怕的忙着等待 sleep() 函数,任何人都不应该在实际代码中使用)是为什么所有 .then() 函数都优先于 onload 事件在 JS 事件循环中?

确实如此,这是因为 Promise 在微任务队列上运行,该队列与主任务队列分开,并且在后者之前排空。

另见this answer to another question

【讨论】:

  • 好吧,这是有道理的。我想这也是 fetch API 出现的原因,因为它是完全“承诺的”! XHR 在 promise 上的表现似乎不太好。
【解决方案2】:

但我不明白为什么它会在继续下载剩余文件之前运行所有“睡眠 1”、“睡眠 2”和“睡眠 3”。

当有多个 Promise 等待解决时,Promise 回调基本上以任意顺序运行1。在您的情况下,它只是选择运行 sequence 的回调(不幸的是,每个回调都需要很长时间),然后再返回解决其他承诺的 ajax 请求的 onload 回调,然后再运行它们的回调继续下载剩余文件。

解决方案很简单:不要使用sleep,也不要使用长时间运行的代码(但要使其异步)。

1:当然,链中的回调 (.then(A).then(B)) 需要按照 Promise 的顺序运行。
并且 Promises/A+ 要求同一个 Promise 上的多个回调按照注册的顺序运行 (p.then(A); p.then(B);)。
并且 ECMAScript6 要求多个已解析的 Promise 上的回调按照 Promise 解析的顺序运行。

【讨论】:

  • 谢谢,sleep 只是一个演示问题的虚拟示例。我想知道为什么它在开始另一个序列之前完成了序列。好像是因为 promises 和 onLoad 事件不在同一个任务队列中运行吧?
  • @Nicolas:是的,这是一个可能的解释;虽然 afaik 浏览器不需要首先处理承诺队列。当然sleep 只是一个假人,但我的意思是,只要你所有异步执行的 sn-ps 都很快(不是长时间运行),你通常不会遇到任何并发问题。
猜你喜欢
  • 1970-01-01
  • 2013-04-03
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
  • 2018-09-03
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多