我正在尝试使用AngularJS构建一个Chrome应用程序,我需要的能力之一是通过Chrome .system.network. getnetworkinterfaces监控可用的网络接口。目前,我正试图将此数据存储在工厂中,并将其注入视图控制器:
(尽量删减)
工厂:exampleApp.factory('exampleFactory', ['$http', function ($http) {
var service = {};
service.network_interfaces = 'Detecting network connections...';
chrome.system.network.getNetworkInterfaces(function(interfaces){
service.network_interfaces = interfaces;
})
// This outputs the expected array containing interface data
// in service.network_interfaces
console.log(service)
return service;
}]);
控制器:
exampleApp.controller('MainCtrl', ['$scope', '$http', 'exampleFactory', function($scope, $http, exampleFactory) {
// This outputs the expected array in network_interfaces, identical
// to the console output within the factory
console.log(exampleFactory)
// But then this outputs the initial 'Detecting network connections...'
// string set in the factory
console.log(exampleFactory.network_interfaces)
// And {{network_interfaces}} and {{factory_state}} in the view keep
// 'Detecting network connections...' as the value for network_interfaces
// permanently
$scope.factory_state = exampleFactory;
$scope.network_interfaces = exampleFactory.network_interfaces;
}]);
:
- 工厂似乎正在返回一个好的
service
对象,但我不确定为什么exampleFactory
和exampleFactory.network_interfaces
会有不同的状态,他们在控制器和工厂之间做,特别是在控制器本身(不管他们被调用的顺序)。 - 我尝试了很多不同的解决方案,假设它是一个异步问题,但我认为在
getNetworkInterfaces
方法上没有明显的延迟,如果有,一切都正确设置为Angular更新{{network_interfaces}}
和{{factory_state}}
视图绑定一旦数据返回。 - 我也试过在工厂用
$rootScope.$apply
包装各种功能,但结果与上面相同。
我四处寻找,想要发现我明显错过的概念,但我想我忽略了一些基本的东西。我如何获得getNetworkInterfaces()数据到我的控制器在一个有用的状态?
你在#2中的假设是问题所在。在调用异步方法和调用它的回调之间,总是有一个JavaScript事件循环的旋转。如果没有,那么在客户机调用该方法时,各种各样的事情都会微妙地中断。这意味着你在Angular开发中遇到了一个常见的问题:你没有收到更改通知,因为更改没有发生在Angular的摘要循环的上下文中。
要解决这个问题:尝试设置一个手表,然后在getNetworkInterfaces()回调中调用$scope.apply()。apply()保证发生在摘要循环之外,因此您不应该得到apply-in-apply错误。
或者,在回调完成后给自己发一个消息。如果你是"如果你使用apply()你的代码是坏的"思想学派的学生,这是更好的。
最后,考虑一个在回调之后调用的Promise。这与您设置代码的方式不太匹配。
(还有,为什么要在工厂中调用async方法?)
试着观察network_interfaces以知道它何时被修改
exampleApp.controller('MainCtrl', ['$scope', '$http', 'exampleFactory', function($scope, $http, exampleFactory) {
// This outputs the expected array in network_interfaces, identical
// to the console output within the factory
console.log(exampleFactory)
// But then this outputs the initial 'Detecting network connections...'
// string set in the factory
console.log(exampleFactory.network_interfaces)
// And {{network_interfaces}} and {{factory_state}} in the view keep
// 'Detecting network connections...' as the value for network_interfaces
// permanently
$scope.factory_state = exampleFactory;
$scope.network_interfaces = exampleFactory.network_interfaces;
$scope.$watch('factory_state.network_interfaces', function() {
console.log($scope.factory_state)
});
}]);