问题
我有一个异步获取数据并将其提供给 Controller 的服务。在那里,它附加到 $scope
并在 View 中使用。
我不明白的是更新的差异,这取决于 Controller 中如何使用此服务。
例子
该服务不提供对数据的 promise ,而是公开数据本身。我在下面用超时模拟了它:
(编辑:我已将初始化添加到 Opt
变量以表明这不能解决问题。)
app.service("Options", ["$q", "$timeout", function ($q, $timeout) {
var Opt = {
people:[],
symbols:[],
countries:[]
};
$timeout(function () {
Opt.people = [ {frst: "Johnny", last: "Walker"},
{frst: "Jack", last: "Daniels"},
{frst: "Jim", last: "Bean"} ];
}, 1000);
$timeout(function () {
Opt.symbols = [ {name: "Pi", descr: "circles"},
{name: "Phi", descr: "ratios"},
{name: "Psi", descr: "waves"},
{name: "Chi", descr: "distributions"} ];
}, 2000);
$timeout(function () {
Opt.cities = [ {name: "Amsterdam", country: "Netherlands"},
{name: "Cairo", country: "Egypt"},
{name: "Santiago", country: "Chile"} ];
}, 3000);
/* etc */
return Opt;
}]);
然后像这样在 Controller 中使用它:
app.controller("Ctrller", ["$scope", "Options", "$timeout", function ($scope, Options, $timeout) {
$scope.options = Options; //updating
$scope.symbols = $scope.options.symbols; //not updating
$scope.symbols = Options.symbols; //not updating either
$timeout(function(){
$scope.symbols = $scope.options.symbols; //updating
}, 4000);
}]);
我在 Plnkr 中创建了一个现场演示 here .
如您所见, View 中的第二个 select
元素(以及 $scope
的 'symbol' 属性)在 4 秒而不是 2 秒后更新。如果 Controller 中没有 $timeout
,当然这根本不会发生。
为什么会这样?为什么更改没有级联通过?
谢谢!
最佳答案
您正在尝试将 $scope.symbols
分配给 $scope.options.symbols
或 Options.symbols
之前的 symbols
数组存在于 Options
服务返回的对象中,因此它 ($scope.symbols
) 被分配 undefined
而不是一个对符号对象的引用。您可以通过在尝试分配之前添加几个控制台语句来查看这一点。由于 symbols
对象尚不存在,您的 $scope.symbols
变量无法引用它。
这不是people
或cities
的问题,因为您是通过引用Opt
服务返回的 Opt
对象。由于基本引用保持不变,您的 ng-repeats
会看到对 people
和 cities
子对象的更改。
如果你真的想将 Options.symbols
分配给 $scope.symbols
,你可以通过监视 $scope.options.symbols< 来完成它
:
$scope.$watch('options.symbols', function(value) {
$scope.symbols = value;
});
在示例 plunker 更新后进行编辑
修改后的 plunker 仍然表现出相同的行为,因为初始化的 people
、cities
和 symbols
在 $ 中被覆盖超时
。如果要保持引用不变,则不得在 $timeout
中使用 =
运算符。一种选择是遍历返回的列表并通过推送添加每个项目:
$timeout(function () {
results = [ {name: "Pi", descr: "circles"},
{name: "Phi", descr: "ratios"},
{name: "Psi", descr: "waves"},
{name: "Chi", descr: "distributions"} ];
angular.forEach(results, function(result) {
Opt.symbols.push(result);
});
}, 2000);
Here is a revised plunker with my suggested changes.
可能有更好的方法来实现这一点,但关键是您不能将 Opt.symbols
重新分配给其他对象(即使其他对象也是数组)。
另一种方法是将 Opt.symbols
更改为内部包含数组的对象,您的引用 $scope.symbols
指向该对象( Opt.symbols
) 并可以查看内部值。
Opt = {
people: [],
symbols: {},
cities: []
}
$timeout(function() {
Opt.symbols.values = [ {name: "Pi", descr: "circles"},
{name: "Phi", descr: "ratios"},
{name: "Psi", descr: "waves"},
{name: "Chi", descr: "distributions"} ];
}, 2000);
如果你走那条路,你需要调整你的 ng-options 看起来像,
ng-options="s as s.name for s in symbols.values"
Here is a working plunker of this approach.
除了我给出的这两种方法之外,您还可以采用其他方法,这对于您的项目来说是有意义的,您必须自己做出决定。关键是,在 $timeout
中,您不能重新分配 Opt.symbols
的值并期望 $scope.symbols
引用新值.
关于javascript - $scope 有选择地更新服务解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26315732/