【问题标题】:async update DOM from Promises从 Promises 异步更新 DOM
【发布时间】:2015-11-29 13:36:02
【问题描述】:

我想通过我的承诺更新 DOM。我构建了一系列 Promise 并使用 Promise.all 运行它们:

function test(i){
  return Promise.resolve()
  .then(function() {
    // update the DOM
    document.getElementById('progress').innerHTML += i;
    return i;
  });
}

var loadSequence = [];
// loop through all the frames!
for (var i = 0; i < 9999; i++) {
  loadSequence.push(test(i));
}

Promise.all(loadSequence)
.then(function(){
  window.console.log('all set...');
});

http://codepen.io/nicolasrannou/pen/jbEVwr

我无法实时更新 DOM。 只有在我的所有承诺都解决后,它才会更新 DOM。

这是预期的行为吗?如果是这样,我如何利用 Promise.all 实时更新我的​​ DOM?

我想使用 promises 而不是“setTimeout(function, 1000)” hack,但我找不到好方法。

【问题讨论】:

  • 我看不出你认为什么是“实时”的?
  • Promise 不是由Promise.all“运行”的,它们只是在等待 - 自您创建它们以来它们已经在运行。
  • Promise.all 等待来自异步函数的一组承诺,这些函数通常并行启动,而不是按顺序启动。

标签: javascript dom asynchronous es6-promise


【解决方案1】:

在浏览器中,DOM 队列会发生变化,如果它们连续发生,而主事件队列没有像你的 for 循环那样的“空闲滴答”,它们将在 JS 操作 DOM 时立即应用完成了。见:https://stackoverflow.com/a/31229816/1207049

要在浏览器环境中克服这个问题,您可以使用setTimeout 将代码执行块推送到不同的队列:

function test(i){
  return Promise.resolve()
  .then(function() {

    // update the DOM
    setTimeout(function() {
      document.getElementById('progress').innerHTML += i;
    }, 0);

    return i;
  });
}

如果没有setTimeout,每条更新元素的innerHTML 的指令都会被推到同一个队列的末尾。使用 setTimeout,它总是进入一个新的空队列,并且可能在主队列中的项目之前执行。

【讨论】:

  • 为什么还要遵守承诺?这根本没有帮助。
  • JS 是单线程的,所以说setTimeout 将“与主执行线程分离”是不对的。承诺在更高优先级的微任务队列上执行,与主事件队列分开,并且通常在主事件队列上当前运行到完成任务的尾部清空,我想你的意思是说。 Promise.resolve() 在使用 setTimeout 时是多余的。相反,考虑一个辅助函数,如:var wait = ms =&gt; new Promise(resolve =&gt; setTimeout(resolve, ms));
  • 是的,我最终使用 set timeout 递归调用函数。当我在一个递归回调中达到我想要的状态时,我解决了这个承诺。
猜你喜欢
  • 2016-06-15
  • 1970-01-01
  • 1970-01-01
  • 2018-04-02
  • 2012-07-31
  • 2018-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多