【问题标题】:Inter-Communication (Directive to Service to Controller)内部通信(向控制器提供服务的指令)
【发布时间】:2013-03-18 09:17:33
【问题描述】:

我正在开发一个多文件上传模块,但在不使用 $rootScope 的情况下从我的服务与我的控制器进行通信时卡住了。

指令监视文件输入并将文件onchange 交给服务,在那里它们被上传并监控上传进度。根据响应(来自成功、错误和进度更改),父控制器应显示拇指和进度。

我不想在我的$rootScope 上使用$emit$on,因为我需要经常安静的模式并且只有一个父控制器需要知道上传。

我创建了一个简化的(!)Plunkr,其中包含一些附加信息以更好地理解问题。

我的控制器是否有其他方式来响应更改(发生在服务工厂内部)?
或者也许是完全不同的实现方式?

【问题讨论】:

    标签: angularjs


    【解决方案1】:

    使用 Angular 处理异步操作的正确方法是使用 promises

    您可以从服务调用返回一个承诺并将其解析为拇指的src。这样你就根本不能使用指令了。

    您的控制器会以这种方式使用服务:

    function ParentController($scope, imageService) {
      $scope.change = function() {
        $scope.src = imageService.change();
    
        $scope.then(function(result) {
          // the loading ended, but there is no need to set the src
          // as it will already bind to src when ends. 
        }, function(err) {
          // something went wrong
        });
      };
     }
    

    您的服务:

    app.factory('imageService', function($q, $rootScope) {
    
      function doTheUploading(defer) {
        if (everythingOk) {
          defer.resolve(thumbSrcString); 
        } else {
          defer.reject({something: 'an error ocurred'});
        }
      }
    
      return {
        change: function() {
          // creates the promise
          var defer = $q.defer();
          doSomethingAsync(defer);
          return defer.promise;
        }
      };
    
    });
    

    至少,您的 HTML 应该如下所示:

    <div ng-controller="ParentController">
      <img src="{{ src }}"><br><br>
      <span class="btn" ng-click="change()">Change!</span>
    </div>
    

    关于进度,您需要使用回调或返回一个可以带来承诺和进度指示器的对象(即:return {promise: defer.promise, percent: 0})。然后应该从服务内部更新进度指示器。

    如果您需要对从服务器返回的 URL 进行任何转换,然后将其设置为 src 属性,您也可以链接您的承诺,即:

    $scope.src = imageService.change().then(function(result) {
        return 'http://dummyimage.com/' + result;
      });
    

    更新your Plunker

    【讨论】:

    • 非常感谢您非常详细的回答 :) 我查看了 Promise API,但我有一个关于进度的问题:只有在解决或拒绝后,我才会返回 Promise 和 Progress,对吧?这意味着进度也是 100 或 0。但是onprogress 是一个持续的事件。而且当我必须使用$emit 来取得进展时,对所有事情都使用事件不是很有意义吗?
    • 返回对象的想法确实很不寻常。另一种解决方案(我更喜欢)是使用回调。将回调传递给服务 (imageService.change(this.handleOnProgress)) 并继续调用它以告知服务内部的进度。我目前正在 Angular 承诺中实现 promise.progress,但我还不知道它是否会被接受/批准,如果它获得批准,我们也不知道它什么时候发货,所以如果你需要它时间,最好去回调。
    • 嗨@JohnB。 promise notification PR has been merged。如果你使用的是不稳定版本或者你自己编译代码,你可以期待下一个版本的这个特性。
    • 很高兴看到它合并。谢谢你告诉我!
    猜你喜欢
    • 2015-05-05
    • 1970-01-01
    • 1970-01-01
    • 2017-06-19
    • 2018-08-05
    • 2015-07-05
    • 1970-01-01
    • 2016-01-12
    • 2013-03-24
    相关资源
    最近更新 更多