1

嗨,我花了两天时间尝试根据异步 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;
}])
4

2 回答 2

1

更新:

这是一个扩展示例,主要使用您的原始代码,展示了如何完全不使用$applyor $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);
<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>


上一个答案:

尽管可能还有其他(更好的)方法,但只需将您的观察值包装在一个函数中。例如:

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

但请注意,这仅在someAsyncservice实际触发摘要循环时才有效(例如,通过使用$q和类似的方法)!

于 2015-06-09T11:13:43.633 回答
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
                });
于 2015-06-09T11:14:13.397 回答