Str*_*lle 14 javascript optimization ajax-polling angularjs
我当前正在轮询服务器以检查新数据,然后相应地更新AngularJS应用程序中的模型.他大致正在做的事情:
setInterval(function () {
$http.get('data.json').then(function (result) {
if (result.data.length > 0) {
// if data, update model here
} else {
// nothing has changed, but AngularJS will still start the digest cycle
}
});
}, 5000);
Run Code Online (Sandbox Code Playgroud)
这很好,但大多数请求不会导致任何新的数据或数据更改,但$ http服务并不真正知道/关心,仍然会触发摘要周期.我认为这是不必要的(因为摘要周期是应用程序中最重的操作之一).有没有办法仍然可以使用$ http,但如果没有任何改变,以某种方式跳过摘要?
一种解决方案是不使用$ http而是使用jQuery,然后调用$ apply让Angular知道模型已经改变:
setInterval(function () {
$.get('data.json', function (dataList) {
if (dataList.length > 0) {
// if data, update model
$scope.value = dataList[0].value + ' ' + new Date();
// notify angular manually that the model has changed.
$rootScope.$apply();
}
});
}, 5000);
Run Code Online (Sandbox Code Playgroud)
虽然这似乎有效,但我不确定这是个好主意.如果可能的话,我仍然想使用纯Angular.
任何人都有任何改进上述方法的建议或完全更优雅的解决方案?
PS我之所以使用setInterval而不是$ timeout是因为$ timeout也会触发一个摘要周期,在这种情况下这是不必要的,只会增加"问题".
AngularJS建议使用PERF技巧,通过$ httpProvider在一个$ digest中捆绑一些$ http响应.这再次,不是解决问题,它只是一种镇静剂:)
$httpProvider.useApplyAsync(true)
Run Code Online (Sandbox Code Playgroud)
首先,接受的解决方案是不可扩展的 - 你不可能在100K行的JS代码项目上做那个$ watchers技巧 - 这是不可能的.
其次,即使项目很小,风险也很大!例如,如果另一个ajax呼叫到达实际需要那些观察者的情况会发生什么?
在不修改AngularJS代码的情况下实现此目的的唯一方法是将$ rootScope.$$阶段设置为true或'$ digest',进行$ http调用,并将$ rootScope.$$阶段设置为null.
$rootScope.$$phase = true;
$http({...})
.then(successcb, failurecb)
.finally(function () {
$rootScope.$$phase = null;
});
Run Code Online (Sandbox Code Playgroud)
风险:
1)其他ajax调用可能会尝试做同样的事情 - >他们需要通过包装ajax服务(超过$ http)进行同步
2)用户可以触发两者之间的UI操作,将$$阶段更改为null的操作以及ajax调用将返回时的操作,并仍然触发$ digest
扫描AngularJS源代码后弹出解决方案 - 这是保存情况的行:https://github.com/angular/angular.js/blob/e5e0884eaf2a37e4588d917e008e45f5b3ed4479/src/ng/http.js#L1272
因为这是每个人都面对AngularJS的问题,我认为需要系统地解决.上面的答案并没有解决问题,只是试图避免它. 所以我们应该创建一个AngularJS拉取请求,允许我们通过$ httpProvider指定一个不会触发特定$ http请求的摘要的配置.希望他们同意这需要以某种方式解决.