问题描述
我试图更好地理解在 Angular 中使用 $timeout 服务作为一种安全的 $apply"方法的细微差别.基本上是在一段代码可以运行以响应 Angular 事件或非 Angular 事件(例如 jQuery 或某些标准 DOM 事件)的情况下.
I'm trying to better understand the nuances of using the $timeout service in Angular as a sort of "safe $apply" method. Basically in scenarios where a piece of code could run in response to either an Angular event or a non-angular event such as jQuery or some standard DOM event.
据我所知:
- 在 $scope.$apply 中包装代码适用于以下情况尚未处于摘要循环中(又名 jQuery 事件),但如果摘要正在进行,则会引发错误
- 在没有延迟参数的 $timeout() 调用中包装代码无论是否已经在摘要循环中都有效
查看 Angular 源代码,看起来 $timeout 调用了 $rootScope.$apply().
Looking at Angular source code, it looks like $timeout makes a call to $rootScope.$apply().
- 如果摘要循环已经在进行中,为什么 $timeout() 也不会引发错误?
- 当您确定摘要不会在进行中时使用 $scope.$apply() 时使用 $timeout() 以确保安全时使用 $timeout() 是最佳做法吗?
- $timeout() 真的是可以接受的安全申请",还是有问题?
感谢您的任何见解.
推荐答案
- 如果摘要循环已经在进行中,为什么 $timeout() 也不会引发错误?
$timeout
使用未记录的 Angular 服务 $browser
.具体来说,它使用 $browser.defer()
通过 window.setTimeout(fn, delay)
异步延迟函数的执行,这将始终在 Angular 生命周期之外运行.只有在 window.setTimeout
触发后,您的函数才会 $timeout
调用 $rootScope.$apply()
.
$timeout
makes use of an undocumented Angular service $browser
. Specifically it uses $browser.defer()
that defers execution of your function asynchronously via window.setTimeout(fn, delay)
, which will always run outside of Angular life-cycle. Only once window.setTimeout
has fired your function will $timeout
call $rootScope.$apply()
.
- 当您确定摘要不会在进行中时使用 $scope.$apply() 时使用 $timeout() 以确保安全时使用 $timeout() 是最佳做法吗?
我会这么说.另一个用例是有时您需要访问 $scope 变量,您知道该变量只会在摘要后初始化.简单的例子是,如果您想在控制器构造函数中将表单的状态设置为脏状态(无论出于何种原因).如果没有 $timeout,FormController
还没有被初始化并发布到 $scope 上,所以将 $scope.yourform.setDirty()
包裹在 $timeout 中可以确保 FormController代码> 已初始化.当然,您可以使用不带 $timeout 的指令完成所有这些操作,只需提供另一个用例示例.
I would say so. Another use case is that sometimes you need to access a $scope variable that you know will only be initialized after digest. Simple example would be if you want to set a form's state to dirty inside your controller constructor (for whatever reason). Without $timeout the FormController
has not been initialized and published onto $scope, so wrapping $scope.yourform.setDirty()
inside $timeout ensures that FormController
has been initialized. Sure you can do all this with a directive without $timeout, just giving another use case example.
- $timeout() 真的是可以接受的安全应用",还是有问题?
它应该始终是安全的,但在我看来,您的 go to 方法应该始终针对 $apply().我正在开发的当前 Angular 应用程序相当大,我们只需要依赖 $timeout 一次而不是 $apply().
It should always be safe, but your go to method should always aim for $apply() in my opinion. The current Angular app I'm working on is fairly large and we've only had to rely on $timeout once instead of $apply().
这篇关于Angular $scope.$apply 与 $timeout 作为安全的 $apply的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!