来自Promises的异步更新DOM

Nic*_*las 3 javascript dom asynchronous es6-promise

我想通过我的承诺更新DOM.我构建了一个promises数组并使用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...');
});
Run Code Online (Sandbox Code Playgroud)

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

我无法实时更新DOM.它只在我的所有承诺都已解决时更新DOM.

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

我想使用promises而不是"setTimeout(function,1000)"hack,但我找不到这样做的好方法.

mar*_*ful 6

在浏览器中,DOM会对更改进行排队,如果它们连续发生而主事件队列没有像for循环一样的"自由滴答",那么当JS操作DOM完成时,它们将立即应用.请参阅:https://stackoverflow.com/a/31229816/1207049

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

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

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

    return i;
  });
}
Run Code Online (Sandbox Code Playgroud)

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

  • JS 是单线程的,所以说`setTimeout` 将“与主执行线程分离”是不对的。Promises 在更高优先级的微任务队列上执行,与主事件队列分开,通常在主事件队列上当前运行到完成任务的尾部清空,我想你的意思是说。Promise.resolve() 在使用 setTimeout 时是多余的。相反,考虑一个辅助函数,如:`var wait = ms =&gt; new Promise(resolve =&gt; setTimeout(resolve, ms));` (4认同)