AngularJS:$q->;延迟API事物顺序(生命周期)和谁调用摘要?
angularjs中的功能非常强大,使用异步代码使我们的生活更加轻松 我不熟悉angular,但使用延迟API对我来说并不陌生。我必须说,我完全同意AngularJS:$q->;延迟API事物顺序(生命周期)和谁调用摘要?,angularjs,angularjs-scope,promise,deferred,angular-promise,Angularjs,Angularjs Scope,Promise,Deferred,Angular Promise,angularjs中的功能非常强大,使用异步代码使我们的生活更加轻松 我不熟悉angular,但使用延迟API对我来说并不陌生。我必须说,我完全同意如何使用文档的一部分+文档中有非常有用的链接+我也查看了源代码 我的问题更多的是关于angular中延迟API和promise API对象的部分。在其生命周期中的确切阶段是什么,以及它们如何与rootScope.Scope(s)交互。我的假设是,当承诺解决时——它调用摘要循环???是/否 能否就以下方面列表提供详细答案: 在你所描述的每一个人身上发生
如何使用
文档的一部分+文档中有非常有用的链接+我也查看了源代码
我的问题更多的是关于angular中延迟API和promise API对象的部分。在其生命周期中的确切阶段是什么,以及它们如何与rootScope.Scope
(s)交互。我的假设是,当承诺解决时——它调用摘要循环???是/否
能否就以下方面列表提供详细答案:
干杯 承诺有三种状态
- 待定-承诺就是这样开始的
- 已实现-这是当您解析延迟或
实现,它通常类似于标准返回值的返回值时发生的情况。然后
- 拒绝-这是当您拒绝延迟的、从
抛出的
处理程序或当您返回一个取消拒绝的承诺*,通常类似于抛出的标准异常时发生的情况。然后
$rootScope.$evalAsync(回调)解析提供保证代码>(取自)
由于它是通过$evalAsync
运行的,我们知道在承诺解决后(通常)至少会发生一个摘要周期,因为如果没有进行一个摘要周期,它会安排一个新的摘要周期
这也是为什么,例如,当您想要在Angular中对承诺代码进行单元测试时,您需要通过$rootScope.digest()
在rootScope
上运行摘要循环,因为$evalAsync执行是摘要循环的一部分
好了,说够了,给我看看代码:
注意:这显示了Angular 1.2中的代码路径,Angular 1.x中的代码路径都很相似,但在1.3中,+$q已经过重构以使用原型继承,因此对于这些版本,这个答案在代码中并不准确(但在精神上)
1) 创建$q时,它会执行以下操作:
这反过来又会:
function qFactory(nextTick, exceptionHandler) {
并且仅在解析和通知中作为$evalAsync
传递的nextTick
上解析:
resolve: function(val) {
if (pending) {
var callbacks = pending;
pending = undefined;
value = ref(val);
if (callbacks.length) {
nextTick(function() {
var callback;
for (var i = 0, ii = callbacks.length; i < ii; i++) {
callback = callbacks[i];
value.then(callback[0], callback[1], callback[2]);
}
});
}
}
},
正如你们所看到的,如果我们不在其中,并且之前没有安排过摘要,那么它确实会安排一个摘要。然后将函数推送到$$asyncQueue
依次在$digest内(在一个周期内,在测试观察者之前):
因此,正如我们所看到的,它在$$asyncQueue
上运行,直到它为空,执行承诺中的代码
因此,正如我们所看到的,更新范围只是简单地分配给它,一个摘要将在它还没有运行时运行,如果已经运行,那么promise中的代码run on$evalAsync
将在运行观察程序之前被调用。因此,一个简单的例子是:
myPromise().then(function(result){
$scope.someName = result;
});
保持简单就足够了
*注意角度区分抛出和拒绝-默认情况下记录抛出,并且必须明确记录拒绝
当承诺解决时-它调用摘要循环
对。您可以通过一个简单的模板进行测试:
{{state}}
以及在延迟后更改$scope.state
变量的控制器代码:
$scope.state = 'Pending';
var d = $q.defer();
d.promise.then(function() {
$scope.state = 'Resolved, and digest cycle must have run';
});
$window.setTimeout(function() {
d.resolve();
}, 1000);
你可以在网站上看到这个。一秒钟后,HTML中的文本显示已解析,并且摘要周期必须已运行
。调用setTimeout
而不是$timeout
是经过深思熟虑的,以确保它必须是resolve
,最终启动摘要循环
通过查看source:通过调用其回调来确认这一点,该函数将回调传递给$rootScope.$evalAsync
,该函数根据:
表达式执行后,将至少执行一个$digest循环
也就是说:
注意:如果在$digest循环之外调用此函数,则将安排一个新的$digest循环
因此,堆栈是否已经在$digest循环中可以更改事件的确切顺序
"一,。您所描述的每个步骤/阶段中发生的事情的顺序是什么
详细介绍上一个示例:
vard=$q.defer()代码>
延迟对象的承诺处于挂起状态。在这一点上,实际上什么都没有发生,您只有一个具有解析
、拒绝
、通知
和承诺
属性的延迟对象。没有使用或影响$digest循环
d.promise.then(函数(){
$scope.state='已解析,且摘要周期必须已运行';
});代码>
承诺仍处于挂起状态,但带有
myPromise().then(function(result){
$scope.someName = result;
});
{{state}}
$scope.state = 'Pending';
var d = $q.defer();
d.promise.then(function() {
$scope.state = 'Resolved, and digest cycle must have run';
});
$window.setTimeout(function() {
d.resolve();
}, 1000);