javascript - $scope 有选择地更新服务解析

标签 javascript angularjs

问题

我有一个异步获取数据并将其提供给 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.symbolsOptions.symbols 之前的 symbols 数组存在于 Options 服务返回的对象中,因此它 ($scope.symbols) 被分配 undefined 而不是一个对符号对象的引用。您可以通过在尝试分配之前添加几个控制台语句来查看这一点。由于 symbols 对象尚不存在,您的 $scope.symbols 变量无法引用它。

这不是peoplecities 的问题,因为您是通过引用Opt 服务返回的 Opt 对象。由于基本引用保持不变,您的 ng-repeats 会看到对 peoplecities 子对象的更改。

如果你真的想将 Options.symbols 分配给 $scope.symbols,你可以通过监视 $scope.options.symbols< 来完成它:

$scope.$watch('options.symbols', function(value) {
    $scope.symbols = value;
});

在示例 plunker 更新后进行编辑

修改后的 plunker 仍然表现出相同的行为,因为初始化的 peoplecitiessymbols$ 中被覆盖超时。如果要保持引用不变,则不得在 $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/

相关文章:

javascript - 表拖动器的基本实现

javascript - Mongoose 查询特定日期范围并获取空值

javascript - 如何设置 ember 引擎?

angularjs - 使用 ui-grid 常量禁用滚动条

angularjs - 如何访问状态参数(ui-sref)而不将它们包含在AngularJS中状态的URL属性中

angularjs - AngularJS中模块之间的通信

JavaScript 添加 onclick 事件到元素

javascript - 在 ng-repeat 中获取对象键

javascript - 动态内容angular js的动态显示隐藏代码

javascript - 如何使用自定义模板在 Angular 中正式设置 modelValue