如何在 AngularJS 中将承诺传递给控制器

How to pass a promise to a controller in AngularJS

我无法理解承诺。我有一个函数 $scope.startJob,当被调用时,它会在 SegmentsService 中调用 areThereAvailableSegments。我的想法是 areThereAvailableSegments 应该 return true 或 false,这样我就可以在控制器中处理这种行为,但不确定该怎么做。

areThereAvailableSegments 调用 getSegments(),后者从数据库请求文本段。 getSegments return 是一个承诺,我正在尝试用 areThereAvailableSegments 中的 .then 来处理这个承诺,但不确定如何传递给控制器​​。

这是我的 Segments 工厂,return 是 $resource 对象,segmentsfactory.js:

angular.module('appApp')
  .factory('SegmentsFactory', function ($resource) {
    return $resource('http://localhost:3000/api/v1/segments/:id');
  });

这是我的 Segments 服务,segmentsservice.js:

angular.module('appApp')
  .service('SegmentsService', function (SegmentsFactory) {

    // gets segments from mongo
    this.getSegments = function(jobId) {
      return SegmentsFactory.query({ job_id: jobId }).$promise;
    };

    // should return true/false if there are available segments
    this.areThereAvailableSegments = function(jobId) {
      var dump = [];

      // queries for all segments
      this.getSegments(jobId)
      .then(function(segments) {
        // dumps segments status in a temp array
        for (var i = 0; i < segments.length; i++) {
          dump.push(segments[i].status);
        }
        // returns true if there is an 'available' in the temp array
        if (dump.indexOf('available') >= 0) {
          return true;
        } else {
          return false;
        }
      });
    };

  });

这是我的控制器,main.js:

$scope.startJob = function() {

  if (SegmentsService.areThereAvailableSegments(jobId)) {
    console.log('there are available segments, then trigger texteditor');
  } else {
    console.log('no segments to translate');
  }
};

执行时,控制台显示"no segments to translate",因为SegmentsService不是return真或假。

如何解决?

没有理由同时拥有服务和工厂。删除工厂并将该代码移至服务中。至于你的问题,你将不得不使用 $q 模块来 return 一个承诺。 https://docs.angularjs.org/api/ng/service/$q

this.areThereAvailableSegments = function(jobId) {
  var dump = [];
  var deferred = $q.deferred;

  // queries for all segments
  this.getSegments(jobId)
  .then(function(segments) {
    // dumps segments status in a temp array
    for (var i = 0; i < segments.length; i++) {
      dump.push(segments[i].status);
    }
    // returns true if there is an 'available' in the temp array
    if (dump.indexOf('available') >= 0) {
      deferred.resolve(true);
    } else {
      deferred.resolve(false);
    }
  });

  return deferred.promise;
};

然后您将不得不在控制器中处理承诺。

函数 areThereAvailibleSegments 也应该 return 一个承诺。 然后在你的控制器中你有一个 then case 并且在那里有你的 if-else。

this.areThereAvailableSegments = function(jobId) {
      var dump = [];

      // queries for all segments
      return this.getSegments(jobId) //Return here
      .then(function(segments) {
        // dumps segments status in a temp array
        for (var i = 0; i < segments.length; i++) {
          dump.push(segments[i].status);
        }
        // returns true if there is an 'available' in the temp array
        if (dump.indexOf('available') >= 0) {
          return true; 
        } else {
          return false;
        }
      });
    };

由于您的成功函数 return 为真或假,areThereAvailibleSegments 函数的承诺将具有该布尔值。

然后在你的控制器中:

SegmentsService.areThereAvailableSegments(jobId).then(function(available){
  if (available) {
      console.log('there are available segments, then trigger texteditor');
    } else {
      console.log('no segments to translate');
    }
});

我会这样设置...在你的工厂完成承诺,然后在控制器中调用数据。

在您的服务 js 中:

    .factory('SegmentsFactory', function ($resource) {

             var APIRequest = {};

            APIRequest.getSegments = function(id){
                    segmentsAPI = $resource('http://localhost:3000/api/v1/segments/'+id'', ;
                    return segmentAPI.get().$promise.then(function(segments){
                        console.log(segments);
                        return segments;
                    });
                };

        return APIRequest;
}]);

然后在你的控制器中:

var dump = [];
        $scope.startJob = function() {

          if (SegmentsService.areThereAvailableSegments) {
             APIRequest.getSegments($scope.id).then(function(data){
                        if (data.error){
                            //error stuff here
                        } else {
                            if (data.segments.length > 0){
                                for(var i=0; i < segments.length; i++){
                                console.log(segments);
                                dump.push(segments[i].status);
        }

    };