来自异步服务的AngularJS绑定值

问题描述:

由于在 Angularjs绑定值中的@sehaxx,已经解决了几个错误服务我想在示例中引入异步,如以下代码所示,其中变量被异步初始化,并且其值未反映在视图中.

Having resolved a couple of errors thanks to @sehaxx in Angularjs binding value from service I would like introduce async in the example as in the following code where a variable is initialized asynchronously and it's value is not reflected in the view.

(function(angular) {
  'use strict';
angular.
module('myServiceModule', []).
  controller('MyController', ['$scope', 'notify','$log', function($scope, notify, $log) {
    this.clickCount = 0;
    this.clickLimit = notify.clickLimit();
    this.callNotify = function(msg) {
        notify.push(msg);
        this.clickCount = notify.clickCount();
        $log.debug("[controller] Click count is now", this.clickCount, " and limit is ", this.clickLimit);
    };

  }]).
factory('notify', ['$window','$log', '$timeout', function(win,$log, $timeout) {
    var msgs = [];
    var clickCounter = 0;
    var countLimit = 0;

    $timeout( function(){
      countLimit = Math.floor(Math.random() * 10)+1;
      $log.debug("[service] Click limit initialized at", countLimit);
      return countLimit;
    }, 10);

    return {
        clickLimit: function(){
          return countLimit;
        },
        clickCount: function() {
            clickCounter = msgs.length;
            $log.debug("[service] You are clicking, click count is now", clickCounter, " limit is ", countLimit);
            return clickCounter;
          },
        push: function(msg) {
              msgs.push(msg);
              clickCounter = msgs.length;
              $log.debug("[service] Counter is", clickCounter, " on ", countLimit);
              if (msgs.length === countLimit) {
                win.alert(msgs.join('\n'));
                msgs = [];
              }
            }
      }
  }]);
})(window.angular);

pen

之所以无法正常工作,是因为countLimit是基元,并且基元总是通过Val而不是byRef传递,因此工厂无法在以后更新值.

The reason this isn't working as expected is due to the fact that countLimit is a Primitive, and Primitives are always passed byVal rather than byRef, so there is no way for the factory to update the value at a later date.

countLimit更改为对象可以解决此问题,因为对象的值是对对象属性的引用.换句话说,我们能够传递byRef.我们只需要更新代码以引用该对象的子属性,而不是直接引用该值,即countLimit.value.

Changing the countLimit to an Object fixes this, because the value of the Object is the Reference to the properties of the Object. In other words, we are able to pass byRef. We just have to update our code to refer to the Object's child property instead of referring to the value directly, i.e. countLimit.value.

工作示例: https://codepen.io/anon/pen/VVmdbE?编辑者= 1111

(function(angular) {
  'use strict';
  angular.
  module('myServiceModule', []).
  controller('MyController', ['$scope', 'notify', '$log', function($scope, notify, $log) {
    this.clickCount = 0;
    this.clickLimit = notify.clickLimit();
    this.callNotify = function(msg) {
      notify.push(msg);
      this.clickCount = notify.clickCount();
      $log.debug("[controller] Click count is now", this.clickCount, " and limit is ", this.clickLimit.value);
    };

  }]).
  factory('notify', ['$window', '$log', '$timeout', function(win, $log, $timeout) {
    var msgs = [];
    var clickCounter = 0;
    var countLimit = {
      value: 0,
    };

    $timeout(function() {
      countLimit.value = Math.floor(Math.random() * 10) + 1;
      $log.debug("[service] Click limit initialized at", countLimit.value);
      return countLimit;
    }, 10);

    return {
      clickLimit: function() {
        $log.debug("called clickLimit");
        return countLimit;
      },
      clickCount: function() {
        clickCounter = msgs.length;
        $log.debug("[service] You are clicking, click count is now", clickCounter, " limit is ", countLimit);
        return clickCounter;
      },
      push: function(msg) {
        msgs.push(msg);
        clickCounter = msgs.length;
        $log.debug("[service] Counter is", clickCounter, " on ", countLimit);
        if (msgs.length === countLimit.value) {
          win.alert(msgs.join('\n'));
          msgs = [];
        }
      }
    }
  }]);
})(window.angular);

<!doctype html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Example - example-services-usage-production</title>


  <script src="https://code.angularjs.org/snapshot/angular.min.js"></script>
  <script src="script.js"></script>



</head>

<body ng-app="myServiceModule">
  <div id="simple" ng-controller="MyController as self">
    <p>Let's try this simple notify service, injected into the controller...</p>
    <input ng-init="message='test'" ng-model="message">
    <button ng-click="self.callNotify(message);">NOTIFY</button>
    <p>(you have to click {{self.clickLimit.value-self.clickCount}} times more to see an alert)</p>
    <div>You have clicked {{ self.clickCount }} times</div>
  </div>

</body>

</html>