gpt4 book ai didi

AngularJS : $q -> deferred API order of things (lifecycle) AND who invokes digest?

转载 作者:行者123 更新时间:2023-12-02 19:08:00 25 4
gpt4 key购买 nike

$q service AngularJS 中非常强大,通过异步代码让我们的生活更轻松。

我是 Angular 新手,但使用延迟 API 对我来说并不是很新鲜。我必须说我完全同意文档的如何使用部分+文档中有非常有用的链接+我也检查了源代码。

我的问题更多是关于 Angular 中延迟和 promise API 对象的底层部分。它们的生命周期的具体阶段是什么,以及它们如何与rootScope.Scope交互。我的假设是,当 promise 解决时 - 它会调用摘要循环???是/否?

能否针对以下几个方面提供具体的详细答案:

  1. 您所描述的每个事件中发生的事情的顺序是什么步骤/阶段
  2. 当创建带有新 Promise 实例的新延迟对象时 - 谁知道它/是它吗重要吗?
  3. 当 Promise 对象被解析时,作用域到底是如何更新的?我是否必须在回调中手动更新它,或者摘要将被自动调用并更新 rootScope like declared here
  4. 至少提及一种在 Promise 回调中更新范围的方法
  5. 我认为还有很多其他有用的方面,请随意提供。

我将欣赏并接受最详细的答案,并尽可能多地引用文档或来源(我自己找不到)。我找不到任何以前与此主题相关的讨论(如果已有讨论),请发布链接。

ps:如果有人为该问题提供更好的标题,请+1,请在评论中添加您的建议。

干杯!

最佳答案

Promise 具有三种状态

  • 待处理 - 这就是 promise 的开始方式。
  • 已实现 - 这是当您解决延迟问题或从 .then 返回值时发生的情况。满足,它通常类似于标准返回值。
  • 拒绝 - 当您 throw 拒绝延期时会发生这种情况。来自.then处理程序或当您返回一个展开为拒绝*的 promise 时,它通常类似于抛出的标准异常。

在 Angular 中,promise 异步解析,并通过 $rootScope.$evalAsync(callback); 解析来提供保证。 (取自 here )。

因为它是通过 $evalAsync 运行的我们知道,在 promise 解决后(通常)至少会发生一个摘要周期,因为如果没有进行中,它将安排一个新的摘要。

这也是为什么,例如,当您想要在 Angular 中对 Promise 代码进行单元测试时,您需要运行摘要循环(通常,通过 rootScope$rootScope.digest() 上运行),因为 $evalAsync 执行是摘要循环的一部分。

好吧,说得够多了,给我看看代码:

注意:这显示了 Angular 1.2 中的代码路径,Angular 1.x 中的代码路径都是相似的,但在 1.3+ $q 中已被重构为使用原型(prototype)继承,因此这个答案不是这些版本的代码是准确的(但精神上是准确的)。

1) 当 $q 创建时,它会 this :

  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {
return qFactory(function(callback) {
$rootScope.$evalAsync(callback);
}, $exceptionHandler);
}];

这又会:

function qFactory(nextTick, exceptionHandler) {

并且仅解析 nextTick传递为$evalAsync内部解析并通知:

  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]);
}
});
}
}
},

在根范围内,$evalAsync 定义为:

  $evalAsync: function(expr) {
// if we are outside of an $digest loop and this is the first time we are scheduling async
// task also schedule async auto-flush
if (!$rootScope.$$phase && !$rootScope.$$asyncQueue.length) {
$browser.defer(function() {
if ($rootScope.$$asyncQueue.length) {
$rootScope.$digest();
}
});
}

this.$$asyncQueue.push({scope: this, expression: expr});
},

$$postDigest : function(fn) {
this.$$postDigestQueue.push(fn);
},

正如您所看到的,如果我们不在其中并且之前没有安排过摘要,则确实会安排摘要。然后它将函数推送到 $$asyncQueue

依次在 $digest 内(在一个周期期间,以及测试观察者之前):

 asyncQueue = this.$$asyncQueue,
...
while(asyncQueue.length) {
try {
asyncTask = asyncQueue.shift();
asyncTask.scope.$eval(asyncTask.expression);
} catch (e) {
clearPhase();
$exceptionHandler(e);
}
lastDirtyWatch = null;
}

因此,正如我们所看到的,它运行在 $$asyncQueue 上直到它为空,执行你的 promise 中的代码。

因此,正如我们所看到的,更新范围只是简单地分配给它,如果摘要尚未运行,则摘要将运行,如果已运行,则 promise 内的代码将在 $evalAsync 上运行在观察者运行之前调用。很简单:

myPromise().then(function(result){
$scope.someName = result;
});

足够了,保持简单。

* 注意 Angular 区分抛出和拒绝 - 默认情况下记录抛出,必须显式记录拒绝

关于AngularJS : $q -> deferred API order of things (lifecycle) AND who invokes digest?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23363014/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com