我试图更好地理解在Angular中使用$ timeout服务的细微差别作为一种" safe $ apply"方法。基本上在一段代码可以运行以响应Angular事件或非角度事件(如jQuery或某些标准DOM事件)的情况下。
据我所知:
查看Angular源代码,看起来$ timeout调用$ rootScope。$ apply()。
感谢您的任何见解。
答案 0 :(得分:60)
查看Angular源代码,看起来$ timeout会调用 $ rootScope。$申请()。
- 如果摘要周期已在进行中,为什么$ timeout()也不会引发错误?
$timeout
使用了未记录的Angular服务$browser
。具体来说,它使用$browser.defer()
通过window.setTimeout(fn, delay)
异步延迟函数的执行,window.setTimeout
将始终在Angular生命周期之外运行。只有$timeout
点击后,您的$rootScope.$apply()
才会调用FormController
。
- 最佳做法是使用$ scope。$ apply()当您确定摘要不会在进行中时,$ timeout()在需要它时是否安全?
我会这么说。另一个用例是,有时你需要访问一个你知道只会在摘要后初始化的$ scope变量。简单的例子是,如果要在控制器构造函数内设置表单的状态为脏(无论出于何种原因)。如果没有$ timeout,$scope.yourform.setDirty()
尚未初始化并发布到$ scope,因此将FormController
包装在$ timeout内可确保{{1}}已初始化。当然,你可以使用没有$ timeout的指令完成所有这些操作,只是给出了另一个用例示例。
- $ timeout()真的是一个可以接受的“安全申请”,还是有问题?
它应该始终是安全的,但是在我看来,你的方法总是应该以$ apply()为目标。我正在处理的当前Angular应用程序相当大,我们只需要依赖$ timeout而不是$ apply()。
答案 1 :(得分:13)
如果我们在应用程序中大量使用$ apply,我们可能会得到错误:$ digest正在进行中。这是因为一次可以运行一个$ digest周期。我们可以通过$ timeout或$ evalAsync来解决它。
$ timeout不会产生“$ digest已在进行中”之类的错误,因为$ timeout告诉Angular在当前周期之后有超时等待,这样它确保了摘要周期之间不会发生任何冲突$ timeout的输出将在新的$ digest循环上执行。
我试图在Comparison of apply, timeout,digest and evalAsync解释它们。
可能会帮助你。
答案 2 :(得分:4)
据我所知,$timeout
是setTimeout
的包装器,它隐含地调用$scope.$apply
,这意味着它在角度生命周期之外运行,但启动角度生命周期本身。唯一的"陷阱"我能想到的是,如果你期望你的结果可以这个 $digest
,你需要找到另一种方法来安全地应用" (其中,AFAIK,仅可通过$scope.$$phase
获得)。