Javascript 是有角度的';s的承诺具有误导性,因为它们并不总是异步调用
我最近在angular.js中调试了一些与promises相关的东西,注意到angular将promises的分辨率放入其evalAsync循环中,如中所示。我的印象是承诺回调总是异步执行的(作为事件队列中的新事件)。然而,使用angular的机制,如果在摘要周期中解析了任何承诺,并且angular在摘要上启动了另一个迭代,则承诺的回调将在同一执行堆栈中调用,因为总是首先检查Javascript 是有角度的';s的承诺具有误导性,因为它们并不总是异步调用,javascript,angularjs,promise,angular-promise,Javascript,Angularjs,Promise,Angular Promise,我最近在angular.js中调试了一些与promises相关的东西,注意到angular将promises的分辨率放入其evalAsync循环中,如中所示。我的印象是承诺回调总是异步执行的(作为事件队列中的新事件)。然而,使用angular的机制,如果在摘要周期中解析了任何承诺,并且angular在摘要上启动了另一个迭代,则承诺的回调将在同一执行堆栈中调用,因为总是首先检查evalAsync队列: do { // "while dirty" loop dirty = false; cu
evalAsync
队列:
do { // "while dirty" loop
dirty = false;
current = target;
while (asyncQueue.length) {
try {
asyncTask = asyncQueue.shift();
asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals);
} catch (e) {
$exceptionHandler(e);
}
lastDirtyWatch = null;
}
traverseScopesLoop:
do { // "traverse the scopes" loop
...
} while ((current = next));
...
} while (dirty || asyncQueue.length);
是不是有误导性?我不确定我是否会称之为误导性。事实是:
- 承诺回调始终异步执行。在
传递给returns之前,不会调用它们。.then()
在更大的程度上,它们甚至从未从用户代码中调用过——堆栈上有“唯一的平台代码”,这是由 - 不能保证每个异步回调都在自己的事件循环回合中执行。没有要求两个回调不能共享相同的事件循环周期。毕竟,他们无论如何也无法区分这一点
在您的例子中,Angular被定义为平台代码,它使用自己的“事件循环”——摘要循环。这就是承诺的工作方式。一个函数实际上无法判断它是在一个特定的事件循环中还是在另一个事件循环中。谢谢,我不知道。我的印象是承诺总是在一个新的事件循环中解析,因为在同一个事件循环中解析并不是真正的异步的,对吧?没错,但因为你的回调不知道会发生什么,所以它必须像异步调用一样编写。实际上,读了一些文章后,我认为我的评论是错误的;promise规范比我想象的更微妙、更健壮,而且我对Angular中发生的事情不太了解,无法判断它。因此,如果我将函数传递给
。然后()在已经实现的promise实例上执行方法,实现必须做一些事情,比如安排立即超时来调用它?或者等到某个间隔计时器找到它?这很奇怪,但规范确实是这么读的。@Pointy:正是这样。规范保证了异步性。没有奇怪的情况,回调有时发生在之前。然后(…)
返回,只是因为承诺意外地已经实现了。好的,对。setImmediate()。这个问题似乎是一个有趣且貌似复杂的问题,超出了基本的行为保证(并不复杂)。@Bergi,谢谢,据我所知,这里的要点是回调在.then()之前从未调用过,但是它们被传递给了returns,当用户代码堆栈存在时,回调可以在与调用.then()
方法的函数相同的事件循环中执行,对吗?@Maximus:是的,它可以在调用then
的相同事件循环中执行,但当堆栈上仍然有一些用户代码时不能执行。一个(人为的)例子是p.then(function(){p.then(/*…later*/);…}/*可以是*now**/)
——内部回调可以在外部回调返回后立即调用。