$apply in setTimeout

Posted

技术标签:

【中文标题】$apply in setTimeout【英文标题】: 【发布时间】:2014-02-23 16:34:36 【问题描述】:

我知道$apply 用于连接 javascript 上下文和 AngularJS 上下文。

一个简单的例子如下:

模板:

<div>someVal</div>

控制器中的javascript:

setTimeout(function() 
    scope.$apply(function()scope.someVal = 123);
, 1000);

我们需要在上述情况下使用$apply

第一个问题:

如果我将上面的 javascript 修改为:

setTimeout(function() 
    scope.someVal = 123;
, 1000);

scope.$watch('someVal', function(val) 
    console.info(someVal);
);

没有控制台关于 someVal 修改为 123... 为什么?不能看超时回调中修改的表达式吗?

第二个问题:

如果我们像下面这样使用 ngSwitch 指令:

<div ng-switch on="sub">
    <div ng-switch-when="a">
//state a
    </div>
    <div ng-switch-when="b">
//state b
    </div>
</div>

当我在控制器中修改sub 时:

scope.sub = 'a';
setTimeout(function() 
    scope.sub = 'b';
, 1000);

无需使用$apply!!!!为什么?

我发现 ngSwitch 指令使用$watch 来监控on 属性值。为什么ngSwitch可以看到超时回调中修改的scope属性??????

请告诉我上面 2 个问题的原因。

【问题讨论】:

第二个问题解决了! someVal 的 $apply 在其他 $apply 中触发,如jsfiddle.net/stefanqi/Jvak8。 【参考方案1】:

来自AngularJs 文档

$apply() 用于从 Angular 框架外部执行 Angular 表达式。 (例如来自浏览器 DOM 事件、setTimeout、XHR 或第三方库)。因为我们正在调用 Angular 框架,所以我们需要执行适当的异常处理范围生命周期,执行 watch。

window.setTimeout 是一个 JavaScript 函数,所以无论你使用 setTimeout 你必须使用 $apply() 来更新模型。

您的第二个示例如果没有$apply() 将无法工作,我制作了一个demo 来澄清$watch$apply 的问题。请检查一下。

【讨论】:

抱歉,我无法访问您的演示。 你是对的!我发现 someVal 的 $apply 是在其他 $apply 中触发的...我对我遇到的情况做了一个小提琴:jsfiddle.net/stefanqi/Jvak8。无论如何,谢谢!【参考方案2】:

您可以使用$timeout,它是 window.setTimeout 的包装器,这样您就不需要在回调中使用 $apply:

$超时(函数() 范围.someVal = 123; , 1000);

当您在 Angular 之外运行代码时,您需要一种方法让 Angular 和该值的观察者知道它已更改。这就是$apply 的用途,它将允许监听器触发

关于第二个问题,为什么范围在没有 $apply 的情况下更新,您应该以某种方式间接触发 $apply/$digest。为了给你一个更具体的答案,一个 Plunker 将是必要的,以检查你的代码中还有什么。

【讨论】:

【参考方案3】:

使用 Angularjs $timeout service 代替 setTimeout,您将不需要 $apply。同样的事情是,如果您使用的是 jquery http 调用,请使用 angular http 服务来避免使用 $apply。

【讨论】:

以上是关于$apply in setTimeout的主要内容,如果未能解决你的问题,请参考以下文章

angularJS报错$apply already in progress的原因和解决方法

ST5222: Advanced Topics in Applied Statistics

[Compose] 21. Apply Natural Transformations in everyday work

WARNING: firstResult/maxResults specified with collection fetch; applying in memory!

熊猫:GroupBy .pipe() 与 .apply()

mybatis-plus小课堂:多表查询案例篇(apply 拼接 in SQL,来查询从表某个范围内的数据)