$ watch Async Service变量不起作用

时间:2015-06-09 11:05:06

标签: javascript angularjs angularjs-watch

您好我过去两天尝试根据异步http服务的响应来创建视图。但它对我不起作用。任何人都可以帮助我吗?

这里有基本概念的代码,但原始代码有点不同:

var myApp = angular.module('app', []);

myApp.directive('dashboard',['service1',function(service1){
    return {
            templateUrl: 'sometemplate.html',
            controller: function ($scope) {

                $scope.data = {};  
                service1.get('keyXXX');
                $scope.$watch(service1.data['keyXXX'],function(n,o){
                    //how to make this work???
                    //I always get null or it would not get executed at all
                });

                }
            }
}])
.service('service1',['someAsyncservice',function(someAsyncservice){

        var _s={
            data:{},
            get:function(key){              
                if(this.data[key]==undefined)
                {
                    this.data[key]={status:"loading",data:{}};
                }
                someAsyncservice().then(function(result){
                    _s[key].data=result;
                    _s[key].status="success";
                });
            }
        }
        return _s;
}])

2 个答案:

答案 0 :(得分:1)

更新

这是一个扩展示例,主要使用您的原始代码,展示了如何完全不使用$apply$watch。只需使用$q,您就可以绕过前两个函数可能产生的大部分问题:



(function (app, ng) {
  'use strict';

  app.controller('TestCtrl', ['$scope', 'RefreshViewService', function ($scope, RefreshViewService) {
    $scope.key = 'key_A';

    $scope.refresh = function refresh(key) {
      $scope.busy = true;

      RefreshViewService.refresh(key).then(function () {
        $scope.busy = false;
      });
    };
  }]);

  app.directive('dashboard', ['service1', function(service1) {
    return {
      template: '<pre><strong>{{ key }}</strong>: {{ data|json }}</pre>',
      scope: {
        key: '@'
      },
      controller: function ($scope) {
        // use currently provided data
        $scope.data = service1.get($scope.key);

        // load data
        service1.load($scope.key).then(function (response) {
          $scope.data = response;
        });
      }
    };
  }]);

  app.service('service1', ['$q', 'someAsyncService', function($q, someAsyncService){
    var data = {}, loading = {};

    return {
      /**
       * returns the currently available data for `key`
       *
       * @param key
       * @returns {*}
       */
      get: function (key) {
        if(data[key] === undefined) {
          data[key] = {
            status: 'loading',
            data:   {}
          };
        }

        return data[key];
      },

      /**
       * async load data for `key`
       *
       * @param key
       * @returns {*}
       */
      load: function(key){
        // clear previous data
        if (loading[key] === undefined) {
          data[key].status = 'loading';
          data[key].data   = {};
        }

        return $q(function (resolve, reject) {
          // only run if not already loading
          if (loading[key] === undefined) {
            loading[key] = someAsyncService(key).then(function(result) {
              data[key].status = 'success';
              data[key].data   = result;

              delete loading[key];

              resolve(data[key]);
            });

          }

          return loading;
        });
      }
    };
  }]);

  /**
   * mock refresh service
   */
  app.service('RefreshViewService', ['service1', function(service1) {
    return {
      refresh: function (key) {
        return service1.load(key);
      }
    };
  }]);

  /**
   * mock async service
   */
  app.service('someAsyncService', ['$q', '$timeout', function ($q, $timeout) {
    return function(key) {
      return $q(function (resolve, reject) {
        $timeout(function () {
          resolve({ 'requested key': key, 'foo': Math.floor(Math.random() * 100) });
        }, 500 + Math.random() * 3000);
      });
    };
  }]);
})(angular.module('app', []), angular);
&#13;
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>

<div data-ng-app="app" class="container">
  <div data-ng-controller="TestCtrl">
    <div class="radio">
      <label>
        <input type="radio" data-ng-model="key" data-ng-disabled="busy" value="key_A"> key A
      </label>

      <label>
        <input type="radio" data-ng-model="key" data-ng-disabled="busy" value="key_B"> key B
      </label>
    </div>

    <button class="btn btn-primary" data-ng-click="refresh(key)" data-ng-disabled="busy">Refresh</button>
    <span data-ng-show="busy">loading...</span>
  </div>

  <hr>

  <dashboard key="key_A"></dashboard>
  <dashboard key="key_A"></dashboard>
  <dashboard key="key_B"></dashboard>
&#13;
&#13;
&#13;

上一个回答:

虽然可能还有其他(更好)的方法,但只需将观看的值包装在一个函数中即可。 E.g:

$watch(function() { return service1.data['keyXXX']; }, ...

但请注意,只有当someAsyncservice实际上触发摘要周期时才能使用此功能(例如,使用$q等)!

答案 1 :(得分:0)

我没有真正测试过,但尝试:

$scope.$watch(function(){return service1.data['keyXXX']},function(n,o){
                    //how to make this work???
                    //I always get null or it would not get executed at all
                });