AngularJS:$q->;延迟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)交互。我的假设是,当承诺解决时——它调用摘要循环???是/否 能否就以下方面列表提供详细答案: 在你所描述的每一个人身上发生

angularjs中的功能非常强大,使用异步代码使我们的生活更加轻松

我不熟悉angular,但使用延迟API对我来说并不陌生。我必须说,我完全同意
如何使用
文档的一部分+文档中有非常有用的链接+我也查看了源代码

我的问题更多的是关于angular中延迟API和promise API对象的部分。在其生命周期中的确切阶段是什么,以及它们如何与
rootScope.Scope
(s)交互。我的假设是,当承诺解决时——它调用摘要循环???是/否

能否就以下方面列表提供详细答案:

  • 在你所描述的每一个人身上发生的事情的顺序是什么 步骤/阶段
  • 当创建了一个新的promise实例的新延迟对象时-谁知道它/它是谁 重要吗
  • 在解析promise对象时,作用域究竟是如何更新的?我是否必须在回调中手动更新它,否则将自动调用摘要并更新根范围
  • 请至少提及一种从promise回调中更新作用域的方法
  • 我假设还有很多其他有用的方面,请随意提供它们
  • 我将感谢并接受最详细的答案,尽可能多地引用文档或来源(我自己找不到)。我找不到以前关于这个话题的任何讨论,如果已经有-请发布链接

    ps:+1对于任何一个能为这个问题提供更好标题的人,请在评论中添加你的建议


    干杯

    承诺有三种状态

    • 待定-承诺就是这样开始的
    • 已实现-这是当您解析延迟或
      的返回值时发生的情况。然后
      实现,它通常类似于标准返回值
    • 拒绝-这是当您拒绝延迟的、从
      抛出的
      时发生的情况。然后
      处理程序或当您返回一个取消拒绝的承诺*,通常类似于抛出的标准异常
    在Angular中,承诺异步解析,并通过
    $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);