AngularJS报错$apply already in progress的解决方法分析
发布时间 - 2026-01-10 22:48:51 点击率:次本文实例分析了AngularJS报错$apply already in progress的解决方法。分享给大家供大家参考,具体如下:

如果我们使用了AngularJS中的$scope.$apply()或者$scope.$digest(),我们很可能会遇到类似下面的错误,虽然这个错误没有太大影响,但是在日志中看起来还是很不爽的,日志中记录的异常或者错误,就应该是需要关注和解决的问题,否则就没有必要出现在日志中了。
Error: [$rootScope:inprog] $apply already in progress http://errors.angularjs.org/1.3.13/$rootScope/inprog?p0=%24apply at angular.js:63 at beginPhase (angular.js:14755) at Scope.$apply (angular.js:14499) at new <anonymous> (1%20-%20%E5%89%AF%E6%9C%AC.html:10) at Object.invoke (angular.js:4185) at extend.instance (angular.js:8454) at angular.js:7700 at forEach (angular.js:331) at nodeLinkFn (angular.js:7699) at compositeLinkFn (angular.js:7078)
下面这段代码就会报上面这个错误:
var myModule = angular.module('myModule', []);
myModule.controller("ctrl_1",function($scope){
$scope.value = "aty";
$scope.$apply();
//$scope.$digest();
});
这个错误其实很好理解:angularJS框架本身已经在做脏数据检测了,我们没有必要再手动调用$apply或者$digest。这里自然而然出现了一个疑问:什么时候需要我们手动调用$apply或者$digest,什么时候不需要呢?这是个好问题,我现在也不知道,目前我只能列出自己在项目中遇到的2种需要手动调用$apply的情况。
情况1:controller中如果有异步操作,比如ajax回调,timeout延时等。可以这么理解:由于异步(延迟)的存在,当开始执行回调函数的时候,angularJS自身controller中的脏值检测已经结束,无法检测到回调函数导致数据的变化。
<html>
<head>
<script src="jquery-1.11.1.min.js"></script>
<script src="angular.js"></script>
<script>
var myModule = angular.module('myModule', []);
myModule.controller("ctrl_1",function($scope){
$scope.text = "place";
setTimeout(function(){
$scope.text = "value setted after time out";
$scope.$apply();//必需手动进行脏值检测,否则数据无法刷新到界面
},1000);
});
$(function(){
angular.bootstrap($("#div1")[0], ["myModule"]);
})
</script>
</head>
<body>
<div id="div1" ng-controller="ctrl_1">
<div>{{text}}</div>
<input id="btn" type="button" value="jquery-event"></input>
</div>
</body>
</html>
这段代码如果没有调用$scope.$apply()的话,数据是不会刷新到界面上的。
情况2:在jQuery代码中修改$scope中的数据。这种情况是在angular框架之外操作$scope中的数据,angular不能检测到数据变化是正常的。
<html>
<head>
<script src="jquery-1.11.1.min.js"></script>
<script src="angular.js"></script>
<script>
var myModule = angular.module('myModule', []);
myModule.controller("ctrl_1",function($scope){
$scope.text = "place";
});
$(function(){
angular.bootstrap($("#div1")[0], ["myModule"]);
$("#btn").click(function(){
var $scope = $("#btn").scope();
$scope.text = "value setted in jquery";
$scope.$apply();
});
})
</script>
</head>
<body>
<div id="div1" ng-controller="ctrl_1">
<div>{{text}}</div>
<input id="btn" type="button" value="jquery-event"></input>
</div>
</body>
</html>
在JQuery的事件处理函数中,我们能够通过dom拿到其关联的$scope对象,进而修改$scope中的数据。这种情况下,也必需要手动调用$scope.$apply()。
也就是说我们必须要清楚哪儿些情况需要手动$apply,哪儿些情况不需要手动$apply,这看起来很简单,实际上并不是这样的。看一段我们项目中的代码:
var myModule = angular.module('myModule', []);
myModule.controller("ctrl_1",function($scope){
$scope.listItems = [];
$scope.loadListFromService = function(){
Spl.MessageProcessor.loadData({
serviceId : "url",
data : {},
success : function(json) {
$scope.listItems = json.results;
// 要不要$scope.$apply()?
},
error: function() {
console.error("invoke service["+optionsJson.serviceId+"] error.");
}
});
}
$scope.loadListFromService();
});
loadData()这个函数很像ajax回调,确实是这样的,这个API不过是做了一点封装,大致代码如下:
function loadData(options)
{
// 从本地缓存中读取,很快
var dataInCache = U.loadDataFromCache(options.serviceId);
if(dataInCache)
{
options.success(dataInCache);
}
else
{
//异步ajax
U.readDataFromServer(options.serviceId, options.data, function(response){
options.success(response);
});
}
}
由于缓存的影响,$scope.loadListFromService()变得不再那么可控,如果本地已经有缓存了,那直接读取缓存是很快的,这个时候不需要手动$apply;如果是第一次,本地没有缓存,那么就变成了情况1,我们需要手动$apply。显然调用loadData()函数的地方,不需要也不应该关注到底有没有缓存的存在,这个时候判断需要不要手动$apply就没有那么容易的。简单粗暴的方式,不管怎么样都手动调用下$scope.$apply(),这样功能不会有问题,但是日志中就不可避免要出现文中开头提到的错误。
angular中的$scope中提供了一个$$phase变量,如果这个变量的值是"$digest" 或者"$apply",就代表angular自身已经在做脏值检测了,不需要我们再去调用$apply或者$digest;否则的话就需要我们手动调用$apply或者$digest了。利用这个属性,我们就可以方便解决上面的错误了,判断一下呗。下面是一个工具函数,好理解吧。
function safeApply(scope, fn) {
(scope.
phase||scope.$root.
phase) ? fn() : scope.$apply(fn);
}
最后提一下,$digest、$apply、$$phase这些属性或者方法其实都是$scope中的私有的,最好不要使用。如果你用到了这些方法,基本可以断言你的代码存在问题,没有按照angular的方式来组织代码。比如情况1中的setTimeout,完全可以用angular中的$timeout代替,这才是推荐的方式,而不是通过$apply来补救。
<html>
<head>
<script src="jquery-1.11.1.min.js"></script>
<script src="angular.js"></script>
<script>
var myModule = angular.module('myModule', []);
myModule.controller("ctrl_1",function($scope, $timeout){
$scope.text = "place";
$timeout(function(){
$scope.text = "value setted after time out";
},1000);
});
$(function(){
angular.bootstrap($("#div1")[0], ["myModule"]);
})
</script>
</head>
<body>
<div id="div1" ng-controller="ctrl_1">
<div>{{text}}</div>
<input id="btn" type="button" value="jquery-event"></input>
</div>
</body>
</html>
所以解决“$apply already in progress”最好的方式,就是不要使用$scope.$apply()或者$scope.$digest()。
更多关于AngularJS相关内容感兴趣的读者可查看本站专题:《AngularJS入门与进阶教程》及《AngularJS MVC架构总结》
希望本文所述对大家AngularJS程序设计有所帮助。
# AngularJS
# 报错
# $apply
# already
# in
# progress
# 解决方法
# angularJS中$apply()方法详解
# 浅谈angular.js中实现双向绑定的方法$watch $digest $apply
# AngularJS中的$watch()
# $digest()和$apply()区分
# 全面解析Angular中$Apply()及$Digest()的区别
# AngularJS中$apply方法和$watch方法用法总结
# Angular项目中$scope.$apply()方法的使用详解
# angularjs 中$apply
# $digest
# $watch详解
# Angular.js中$apply()和$digest()的深入理解
# AngularJS双向数据绑定原理之$watch、$apply和$digest的应用
# Angularjs中的$apply及优化使用详解
# 不需要
# 回调
# 也不
# 是这样
# 什么时候
# 这段
# 这个时候
# 检测到
# 都是
# 是一个
# 进阶
# 就会
# 是在
# 很好
# 会有
# 相关内容
# 最好的
# 我现在
# 出现在
# 可以用
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
如何为不同团队 ID 动态生成多个“认领值班”按钮
Win11怎么关闭透明效果_Windows11辅助功能视觉效果设置
Laravel全局作用域是什么_Laravel Eloquent Global Scopes应用指南
Laravel怎么发送邮件_Laravel Mail类SMTP配置教程
怎么用AI帮你设计一套个性化的手机App图标?
JavaScript中如何操作剪贴板_ClipboardAPI怎么用
如何生成腾讯云建站专用兑换码?
Laravel如何设置自定义的日志文件名_Laravel根据日期或用户ID生成动态日志【技巧】
高端智能建站公司优选:品牌定制与SEO优化一站式服务
Laravel怎么生成二维码图片_Laravel集成Simple-QrCode扩展包与参数设置【实战】
Laravel怎么使用Intervention Image库处理图片上传和缩放
Laravel怎么实现微信登录_Laravel Socialite第三方登录集成
合肥制作网站的公司有哪些,合肥聚美网络科技有限公司介绍?
如何快速搭建高效WAP手机网站吸引移动用户?
百度浏览器网页无法复制文字怎么办 百度浏览器复制修复
Laravel如何与Vue.js集成_Laravel + Vue前后端分离项目搭建指南
QQ浏览器网页版登录入口 个人中心在线进入
高性能网站服务器配置指南:安全稳定与高效建站核心方案
Laravel如何使用Service Provider服务提供者_Laravel依赖注入与容器绑定【深度】
Laravel的.env文件有什么用_Laravel环境变量配置与管理详解
轻松掌握MySQL函数中的last_insert_id()
Laravel如何创建自定义Artisan命令?(代码示例)
JS去除重复并统计数量的实现方法
高性价比服务器租赁——企业级配置与24小时运维服务
微信公众帐号开发教程之图文消息全攻略
EditPlus中的正则表达式实战(6)
Android 常见的图片加载框架详细介绍
谷歌浏览器下载文件时中断怎么办 Google Chrome下载管理修复
JS实现鼠标移上去显示图片或微信二维码
如何在建站之星网店版论坛获取技术支持?
免费网站制作appp,免费制作app哪个平台好?
HTML5空格和margin有啥区别_空格与外边距的使用场景【说明】
javascript如何操作浏览器历史记录_怎样实现无刷新导航
谷歌浏览器如何更改浏览器主题 Google Chrome主题设置教程
如何在IIS中配置站点IP、端口及主机头?
简历在线制作网站免费版,如何创建个人简历?
如何用低价快速搭建高质量网站?
Laravel的路由模型绑定怎么用_Laravel Route Model Binding简化控制器逻辑
Laravel的Blade指令怎么自定义_创建你自己的Laravel Blade Directives
历史网站制作软件,华为如何找回被删除的网站?
如何在橙子建站上传落地页?操作指南详解
JavaScript Ajax实现异步通信
新三国志曹操传主线渭水交兵攻略
Laravel如何实现URL美化Slug功能_Laravel使用eloquent-sluggable生成别名【方法】
制作电商网页,电商供应链怎么做?
Laravel队列任务超时怎么办_Laravel Queue Timeout设置详解
如何用虚拟主机快速搭建网站?详细步骤解析
为什么要用作用域操作符_php中访问类常量与静态属性的优势【解答】
黑客如何利用漏洞与弱口令入侵网站服务器?
Laravel如何实现多对多模型关联?(Eloquent教程)

