【问题标题】:AngularJS scope variable not setting properlyAngularJS范围变量设置不正确
【发布时间】:2018-12-21 22:46:18
【问题描述】:

我正在使用electron-json-storage 并且我正在尝试将AngularJS $scope 变量设置为等于存储的数据。

下面是我的代码:

portal.controller('portalViewController', function($scope) {
    //$scope.url = "http://www.google.com"; //correctly sets $scope.url to google.com
    storage.get('portal_url', (err, data) => {
        console.log(data.url); //prints out data as it should
        $scope.url = data.url;
    });
});

如您所见,我有这个工作的每个单独的组件,但是当我将它们组合起来时,$scope.url 似乎没有设置好。我已经坚持了一段时间,无法弄清楚问题是什么。我对 AngularJS 还很陌生,所以这可能是我所缺少的非常简单的东西。

感谢您提供的任何帮助!

【问题讨论】:

  • storage.get 可能不会触发摘要循环,并且您的 $scope 变量没有被反映。可以尝试使用$scope.$apply() 进行确认,但您不应该使用它作为解决方案。

标签: javascript angularjs electron


【解决方案1】:

由于storage 似乎是第三方插件,因此$scope 的任何更改都不会执行摘要循环。使用 $timeout 强制执行摘要循环,以便在 UI 中呈现更改。

portal.controller('portalViewController', function($scope, $timeout) {
    storage.get('portal_url', (err, data) => {
        console.log(data.url); //prints out data as it should
        $timeout(function(){
            $scope.url = data.url;
        });
    });
});

【讨论】:

    【解决方案2】:

    如果回调确实来自 AngularJS 执行上下文之外的第三方源,则可以简单地使用$apply

    portal.controller('portalViewController', function($scope) {
        storage.get('portal_url', (err, data) => {
            $scope.$apply(function() {
                $scope.url = data.url;
            });
        });
    });
    

    来自文档:

    AngularJS 通过提供自己的事件处理循环来修改正常的 JavaScript 流程。这将 JavaScript 拆分为经典和 AngularJS 执行上下文。只有在 AngularJS 执行上下文中应用的操作才能受益于 AngularJS 数据绑定、异常处理、属性监视等……您也可以使用 $apply() 从 JavaScript 进入 AngularJS 执行上下文。

    请记住,在大多数地方(控制器、服务)$apply 已经被处理事件的指令调用。只有在实现自定义事件回调或使用第三方库回调时,才需要显式调用 $apply

    — AngularJS Developer Guide - Integration with the browser event loop


    将基于回调的 API 转换为基于 AngularJS Promise 的 API

    可以通过创建服务将基于回调的 API 集成到 AngularJS 框架中:

    app.service("storageAPI", function($q) {
        this.get = function(url) {
            var deferred = $q.defer();
            storage.get(url, (err, data) => {
                if (err) { 
                    deferred.reject(err);
                } else {
                    deferred.resolve(data);
                };
            });
            return deferred.promise;
        };
    });
    

    用法:

    app.controller('portalViewController', function($scope, storageAPI) {
        storageAPI.get('portal_url')
          .then(function(data) {
             $scope.url = data.url;
        }).catch(function(err) {
             console.log(err);
        });
    });
    

    这种方法的优势在于它将 API 集成到 AngularJS 框架中,而不需要 $apply($q 服务会自动执行此操作)。此外,它还可以稳健地处理来自 API 的错误。

    有关详细信息,请参阅 - AngularJS $q Service API Reference - The Deferred API.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-16
      • 1970-01-01
      • 1970-01-01
      • 2013-09-23
      • 1970-01-01
      • 2016-04-30
      • 1970-01-01
      相关资源
      最近更新 更多