【问题标题】:Angular Service working synchronously with ControllerAngular Service 与 Controller 同步工作
【发布时间】:2016-08-01 13:29:36
【问题描述】:

我对 AngularJS 还很陌生,并且刚刚开始掌握许多我特别喜欢 MVC 设计模式的概念。但是我很难在我的应用程序中实现服务层。

我发现,在我的控制器调用服务中的方法后,它会在服务返回数据之前继续执行代码;这样当服务返回数据时,它对控制器没有任何用处。

为了更好地说明我的意思,下面是代码:

var InsightApp = angular.module('InsightApp', ['chart.js']);

// Module declaration with factory containing the service
InsightApp.factory("DataService", function ($http) {
return {
    GetChartSelections: function () {
            return $http.get('Home/GetSalesData')
                .then(function (result) {
                return result.data;
            });
        }
    };
});

InsightApp.controller("ChartSelectionController", GetAvailableCharts);

// 2nd Controller calls the Service
InsightApp.controller("DataController", function($scope, $http, DataService){
var response = DataService.GetChartSelections();

// This method is executed before the service returns the data 
function workWithData(response){
    // Do Something with Data
   }
}

我发现的所有示例似乎都按照我在这里的方式构建或略有不同;所以我不确定我应该做些什么来确保异步执行。

在 Javascript 世界中,我会将服务移至 Controller 内部,以确保它异步执行;但我不知道如何在 Angular 中实现这一点。此外,无论如何,这样做与角度注入是反直觉的。

那么正确的做法是什么?

【问题讨论】:

  • 人人都说回报承诺! Angular 2 合并了 RxJS(反应式扩展)。 Angular 1 你必须自己做,但想法是一样的。这是你必须学习的Observer => Observable 模式。

标签: javascript angularjs model-view-controller


【解决方案1】:

http 返回一个承诺而不是数据,因此在您的工厂中,您返回 $http 承诺,并且可以像使用 then、catch、finally 方法的承诺一样使用它。

见:http://blog.ninja-squad.com/2015/05/28/angularjs-promises/

InsightApp.controller("DataController", function($scope, $http, DataService){

var response = DataService.GetChartSelections()
    .then(function(res) {
       // execute when you have the data
    })
    .catch(function(err) {
      // execute if you have an error in your http call
    });

编辑将参数传递给模型服务:

InsightApp.factory("DataService", function ($http) {
return {
    GetChartSelections: function (yourParameter) {
            console.log(yourParameter);
            return $http.get('Home/GetSalesData')
                .then(function (result) {
                return result.data;
            });
        }
    };
});

然后:

InsightApp.controller("DataController", function($scope, $http, DataService){

var response = DataService.GetChartSelections('only pie one')
    .then(function(res) {
       // execute when you have the data
    })
    .catch(function(err) {
      // execute if you have an error in your http call
    });

【讨论】:

  • 谢谢!这正是我想要的。它工作服务和控制器工作异步,响应实际上提供了预期的数据。
  • 我知道这不是我的问题的最初部分,而是对您的回答进行了一点扩展;如何使用此模型将参数传递给同一服务??
  • 太好了,谢谢。变量被适当地传递给服务,但 $http 调用没有将变量传递给方法。花了一点时间来弄清楚那部分,但现在效果很好。再次感谢 ;-)
【解决方案2】:

你应该这样做:

DataService.GetChartSelections().then(function (data) {
     workWithData(data);
}

实际上 $http.get 返回一个 Promise。然后你可以调用该方法来处理你的 Promise 的成功或失败

【讨论】:

    【解决方案3】:

    当你的 $http 返回一个 promise 或者你传递一个回调时,不应该是这样吗?

    callback 传递为param

    InsightApp.factory("DataService", function ($http) {
    return {
        GetChartSelections: function (workWithData) {
                return $http.get('Home/GetSalesData')
                    .then(function (result) {
                    workWithData(result.data);
                });
            }
        };
    });
    

    控制器代码:

    InsightApp.controller("DataController", function($scope, $http, DataService){
    var response = DataService.GetChartSelections(workWithData);
    
    // This method is executed before the service returns the data 
    function workWithData(response){
        // Do Something with Data
       }
    }
    

    或者使用 then 或者 success:

    var response = DataService.GetChartSelections().then(function(res){
          //you have your response here... which you can pass to workWithData
    });
    

    【讨论】:

      【解决方案4】:

      将promise返回给控制器,不要在工厂解决它

          var InsightApp = angular.module('InsightApp', ['chart.js']);
      
          // Module declaration with factory containing the service
          InsightApp.factory("DataService", function ($http) {
          return {
              GetChartSelections: function () {
                      return $http.get('Home/GetSalesData');
                  }
              };
          });
      

      在控制器中,

      var successCallBk =function (response){
          // Do Something with Data
      };
      var errorCallBK =function (response){
          // Error Module
      };
      
      var response = DataService.GetChartSelections().then(successCallBk,errorCallBK);
      

      【讨论】:

      • 您的代码示例似乎确保异步执行,但响应是 OK 的 http 状态代码。它不包含数据。有什么想法吗?
      • 必须使用response.data获取数据
      猜你喜欢
      • 2018-07-21
      • 2019-01-07
      • 1970-01-01
      • 1970-01-01
      • 2018-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多