$digest already in progress 解决办法

时间:2021-02-27 23:01:49

Solution

In short, instead of doing this:

... your controller code...

$http.get('some/url', function(data){
$scope.$apply(function(){
$scope.mydate = data.mydata;
});
}); ... more of your controller code...

do this:

... your controller code...

$http.get('some/url', function(data){
$timeout(function(){
$scope.mydate = data.mydata;
});
}); ... more of your controller code...
参考:http://*.com/questions/12729122/angularjs-prevent-error-digest-already-in-progress-when-calling-scope-apply

$apply()和$digest()在AngularJS中是两个核心概念,但是有时候它们又让人困惑。而为了了解AngularJS的工作方式,首先需要了解$apply()和$digest()是如何工作的。这篇文章旨在解释$apply()和$digest()是什么,以及在日常的编码中如何应用它们。

探索$apply()和$digest()

AngularJS提供了一个非常酷的特性叫做双向数据绑定(Two-way Data Binding),这个特性大大简化了我们的代码编写方式。数据绑定意味着当View中有任何数据发生了变化,那么这个变化也会自动地反馈到scope的数据上,也即意味着scope模型会自动地更新。类似地,当scope模型发生变化时,view中的数据也会更新到最新的值。那么AngularJS是如何做到这一点的呢?当你写下表达式如{{ aModel }}时,AngularJS在幕后会为你在scope模型上设置一个watcher,它用来在数据发生变化的时候更新view。这里的watcher和你会在AngularJS中设置的watcher是一样的:

$scope.$watch(‘aModel‘, function(newValue, oldValue) {
//update the DOM with newValue
});

传入到$watch()中的第二个参数是一个回调函数,该函数在aModel的值发生变化的时候会被调用。当aModel发生变化的时候,这个回调函数会被调用来更新view这一点不难理解,但是,还存在一个很重要的问题!AngularJS是如何知道什么时候要调用这个回调函数呢?换句话说,AngularJS是如何知晓aModel发生了变化,才调用了对应的回调函数呢?它会周期性的运行一个函数来检查scope模型中的数据是否发生了变化吗?好吧,这就是$digest循环的用武之地了。在$digest循环中,watchers会被触发。当一个watcher被触发时,AngularJS会检测scope模型,如何它发生了变化那么关联到该watcher的回调函数就会被调用。那么,下一个问题就是$digest循环是在什么时候以各种方式开始的?在调用了$scope.$digest()后,$digest循环就开始了。假设你在一个ng-click指令对应的handler函数中更改了scope中的一条数据,此时AngularJS会自动地通过调用$digest()来触发一轮$digest循环。当$digest循环开始后,它会触发每个watcher。这些watchers会检查scope中的当前model值是否和上一次计算得到的model值不同。如果不同,那么对应的回调函数会被执行。调用该函数的结果,就是view中的表达式内容(译注:诸如{{ aModel }})会被更新。除了ng-click指令,还有一些其它的built-in指令以及服务来让你更改models(比如ng-model,$timeout等)和自动触发一次$digest循环。

目前为止还不错!但是,有一个小问题。在上面的例子中,AngularJS并不直接调用$digest(),而是调用$scope.$apply(),后者会调用$rootScope.$digest()。因此,一轮$digest循环在$rootScope开始,随后会访问到所有的children scope中的watchers。

随机推荐

  1. Android判断网路是否畅通加权限

    权限 <uses-permission android:name="android.permission.INTERNET"/> <uses-permission ...

  2. Strint类成员

    String& String::operator=(const string& other){ if(this == &other) {  return *this; } de ...

  3. Tomcat指定特定JDK版本

    我们知道在Linux服务器上,可以安装多个版本的JDK,那么当有多个JDK时,是否可以为Tomcat这类应用程序指定对应的JDK版本呢?答案是可以,指定tomcat使用特定的JDK版本.今天正好碰到这 ...

  4. &lpar;转&rpar;无法将类型为&OpenCurlyDoubleQuote;Microsoft&period;Office&period;Interop&period;Word&period;ApplicationClass”的 COM 对象强制转换为接口类型&OpenCurlyDoubleQuote;Microsoft&period;Office&period;Interop&period;Word&period;&lowbar;Application”。此操作失败的原因是对 IID 为&OpenCurlyDoubleQuote;&lbrace;00020970-

    HRESULT:0x80030002 无法将类型为“Microsoft.Office.Interop.Word.ApplicationClass”的 COM 对象强制转换为接口类型“Microsoft ...

  5. Linux splint命令

    一.简介 splint是一个针对C语言的开源程序静态分析工具. 二.安装配置 1)yum安装 yum install -y splint 2)源码安装 http://www.splint.org/ 配 ...

  6. html-----007

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. html基础标签-1-pre预格式标签

    pre预格式标签 code,tt标签 1 <!doctype html> 2 <html lang='zh-cn'> 3 <head> 4 <meta cha ...

  8. error 和 exception 有什么区别&quest;

    1.error指恢复不是不可能但非常困难的情况下的一种严重错误.比如内存溢出,不指望程序可以处理这样的情况. 2.exception表示一种设计或者实现问题,如果程序正常运行,则从不会发生.

  9. 操作Frame和IFrame中页面元素

    HTML <iframe> 标签 定义:iframe 元素会创建包含另外一个文档的内联框架(即行内框架). frame标签有frameset.frame.iframe三种,frameset ...

  10. JavaScript函数箭头的优势在哪里

    译者按: 看上去只是语法的变动,其实也影响了this的作用域. 原文: JavaScript: Arrow Functions for Beginners 译者: Fundebug 为了保证可读性,本 ...