2015-11-10 65 views
0

我在尝试测试事件监听器中的Promise时遇到了问题。一切都很好,但执行顺序。Promise中同步执行的顺序

var test = document.querySelector('#test'); 
 
test.addEventListener('click',function(){ 
 
    Promise.resolve().then(function(){ 
 
     throw 'first'; 
 
    }).catch(function(er){ 
 
    \t console.log(er); 
 
    }); 
 
}); 
 
test.addEventListener('click',function(){ 
 
    console.log('second'); 
 
}); 
 
test.click();
<div id="test"></div>

为什么不是第一个监听前面第二收听完吗?

+3

'then'的回调异步调用其他代码。 – zerkms

+0

“完成”是什么意思? – Bergi

+0

@zerkms你怎么知道的?你有任何文档或东西?这是一个错误还是预期的行为? – Lewis

回答

1

它的行为就像按照标准要求:

  • 否则,如果承诺的[[PromiseState]]内部槽的值是"fulfilled"
    a。让价值成为承诺的[[PromiseResult]]内部插槽的价值。 b。执行EnqueueJob("PromiseJobs", PromiseReactionJob, «‍fulfillReaction, value»)
  • 否则,如果承诺的[[PromiseState]]内部槽的值为"rejected",
    a。让理由成为承诺的[[PromiseResult]]内部插槽的价值。 b。执行EnqueueJob("PromiseJobs", PromiseReactionJob, «‍rejectReaction, reason»)
  • 所以,当一个承诺解决或拒绝一个相应的回调被安排在后面跑,异步于当前执行。

    参考文献:

    +0

    非常感谢规范解释。我认为异步执行通常应用于*长期运行*操作(I/O,CPU密集型等)。在这种情况下实施它是没有意义的。你有什么想法为什么'Promise.then'是异步? – Lewis

    +1

    那么,我知道它最初是['Promises/A +'](https://promisesaplus.com/)它需要它那样。我不确定,但是内置的Promise有可能采用了这种行为。就我个人而言,我不知道他们是异步的技术原因是什么。另一方面 - 我意识到,即使*如果他们已经解决/拒绝的承诺是同时发生的 - 你仍然不会依赖于此,因为那样你就会有两种不同的行为。所以也许最初的想法是提供一致的行为。 – zerkms

    +1

    @zerkms:确切地说,'then'回调*一致*(可靠)异步执行。 – Bergi

    1

    第二个侦听器不依赖于第一个侦听器(承诺),因此它们异步工作。你为什么要将它们分开?可以简单地使用下面的代码

    Promise 
         .resolve() 
         .then(function(){ 
          throw 'first'; 
         }) 
         .catch(function(er){ 
          console.log(er); 
         }) 
         .finally(function(er) { 
          console.log('second'); 
         }; 
        }); 
    
    +0

    我已经知道他们是异步执行的。但是,如果'Promise.then'是同步的,则应该颠倒执行顺序。 – Lewis

    +0

    @JaromandaX你没有明白我的观点。事件监听器显然是异步执行的,但是'Promise.then'。我这么说是因为我认为最好有一个'Promise.then'的同步版本。 – Lewis

    +0

    我试图理解@Tresdin。好的,我们知道'Promise.resolve()'和'console.log('second')'是两个异步代码块。 'Promise.resolve()'需要更多的时间来执行,所以这就是为什么你首先看到'console.log('second')'运行。在这种情况下,如果你希望你的'console.log('second')'在第一个监听器后自信地运行,你必须把它放在'then,catch或finally'块中,这就是我们所说的同步执行:)希望我有你的点@Tresdin –