Angular $ scope。$ apply vs $ timeout作为一个安全的$ apply

我试图更好地理解在Angular中使用$ timeout服务作为一种“安全的$应用”方法的细微差别。 基本上,在一段代码可以运行以响应Angular事件或非angular度事件(如jQuery或某个标准的DOM事件)的情况下。

据我所知,

  1. 在$ scope中包装代码$ apply对于不在digest循环中(也就是jQuery事件)的场景来说工作正常,但是如果摘要正在进行
  2. 在没有延迟参数的情况下,在$ timeout()调用中包装代码是否已经在摘要循环中工作

看一下Angular的源代码,看起来像$ timeout调用$ rootScope。$ apply()。

  1. 为什么如果一个摘要循环已经在进行,$ timeout()也会引发一个错误?
  2. 最好的做法是使用$ scope。$ apply()当你知道一个摘要不会已经在进行中,$ timeout()的时候需要它是安全的吗?
  3. $超时()真的是一个可以接受的“安全适用”,或者有问题吗?

感谢您的任何见解。

看一下Angular的源代码,看起来像$ timeout调用$ rootScope。$ apply()。

  • 为什么如果一个摘要循环已经在进行,$ timeout()也会引发一个错误?

$timeout使用一个无证的Angular服务$browser 。 具体来说,它使用$browser.defer() ,通过window.setTimeout(fn, delay)asynchronous执行你的函数,这个函数总是在Angular的生命周期之外运行。 只有一次window.setTimeout已经触发你的函数$timeout调用$rootScope.$apply()

  • 最好的做法是使用$ scope。$ apply()当你知道一个摘要不会已经在进行中,$ timeout()的时候需要它是安全的吗?

我会这样说。 另一个用例是有时你需要访问一个$ scopevariables,你知道它只会在摘要之后被初始化。 简单的例子是,如果你想在你的控制器构造函数中设置一个表单的状态为脏(不pipe出于什么原因)。 如果没有$ timeout, FormController还没有被初始化并发布到$ scope上,所以在$ timeout里封装$scope.yourform.setDirty()可以确保FormController已经被初始化了。 当然你可以用一个没有$ timeout的指令来做所有这些,只是给出另一个用例的例子。

  • $超时()真的是一个可以接受的“安全适用”,或者有问题吗?

它应该总是安全的,但是你的方法应该总是针对$ apply()在我看来。 目前我正在使用的Angular应用程序相当庞大,我们只需要依靠$ timeout一次而不是$ apply()。

如果我们在应用程序中大量使用$,我们可能会得到Error:$ digest已经在进行中。 这是因为一次可以运行一个$ digest循环。 我们可以通过$ timeout或者$ evalAsync来解决它。

$ timeout不会产生像“$摘要已在进行中”的错误,因为$ timeout告诉Angular在当前周期之后有一个超时等待,这样就保证了在摘要周期之间不会有任何冲突,从而输出$超时将在新的$摘要循环中执行。

我试图解释他们在比较应用,超时,摘要和evalAsync 。

可能会帮助你。

据我了解, $timeoutsetTimeout一个包装器,它隐式地调用$scope.$apply ,这意味着它在angular度生命周期之外运行,但是kickstartangular度生命周期本身。 我能想到的唯一的“陷阱”是,如果你期望你的结果是可用的这个 $digest ,你需要find另一种“安全应用”的方式(AFAIK只能通过$scope.$$phase )。