AngularJS $http 在服务中调用,返回解析的数据,而不是承诺 [英] AngularJS $http call in a Service, return resolved data, not promises

查看:21
本文介绍了AngularJS $http 在服务中调用,返回解析的数据,而不是承诺的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否可以进行使用 $http 的服务调用,以便它直接返回数据而不返回承诺?我曾尝试使用 $q 并没有任何运气.

I want to know if it is possible to make a service call that uses $http so it returns data directly without returning a promise? I have tried to use the $q and defer without any luck.

我的意思是:

我有一项服务:

angular.module('myModule').factor('myService', ['$http', '$q',
    function($http, $q) {

        // Public API
        return {
            myServiceCall: function() {
                return $http.get('/server/call');
            }
        };
    }
]);

这就是我的称呼:

// My controller:
myService.myServiceCall().then(function(data) {
  $scope.data = data;
});

我想避免这种情况,而是希望拥有:

I want to avoid that and instead wish to have:

$scope.data = myService.myServiceCall();

我希望它在那条线上得到完全解决,可能吗?

I want it to be fully resolved at that line, is it possible?

我尝试了 $q、defer 和 'then' 方法的一些组合,但似乎无法正确组合,因为该方法立即返回.

I have tried some combinations of $q, defer and 'then' methods but can't seem to get it right since the method returns immediately.

如果你想知道为什么,主要原因是我想简化控制器代码,这很容易用 ngResource 完成,因为这些调用在模板中自动解析,所以我想避免需要做整个 '.then' 每次.

If you are wondering why, the main reason is that I wanted to simplify the controller code, this is easily done with ngResource as those calls are automatically resolved in templates, so I wanted to avoid the need to do the the whole '.then' everytime.

并不是我不喜欢 Async 性质,我们的大部分代码都利用了它,只是在某些情况下,采用同步方式是有帮助的.

It's not that I don't like the Async nature, most of our code leverages it, it's just in some cases, having a synchronous way is helpful.

我认为现在正如你们中的一些人指出的那样,我将使用 $resource 来获得足够接近的解决方案.

I think for now as some of you have pointed out, I will use the $resource for a near enough solution.

推荐答案

我可以想到两种方法来做到这一点.第一个肯定比第二个好.

There are two ways I can think of to do this. The first is definitely better than the second.

您可以使用路由配置对象的 resolve 属性来指定必须解析一个承诺并将解析的值用于您的控制器依赖项之一的值,以便尽快您的控制器运行,该值立即可用.

You can use the resolve property of the route configuration object to specify that a promise must be resolved and the resolved value be used for the value of one of your controller dependencies, so that as soon as your controller runs, the value is immediately available.

例如,假设您有以下服务:

For example, say you have the following service:

app.service('things', ['$http', '$q', function ($http, $q) {
    var deferred = $q.defer();

    $http({
        method: 'GET',
        url: '/things',
        cache: true
    }).success(function (data) {
        deferred.resolve(data);
    }).error(function (msg) {
        deferred.reject(msg);
    });

    return deferred.promise;
}]);

然后你可以像这样定义你的路线:

Then you could define your route something like this:

$routeProvider.when('/things', {
    controller: ['$scope', 'thingsData', function ($scope, thingsData) {
        $scope.allThings = thingsData;
    }],
    resolve: {
        thingsData: ['things', function (things) {
            return things;
        }]
    }
});

resolve 对象中的键对应于控制器的第二个依赖项的名称,因此即使它返回一个承诺,该承诺也会在控制器运行之前被解析.

The key in the resolve object corresponds to the name of the second dependency for the controller, so even though it returns a promise, that promise will be resolved before the controller is run.

第二种方式一点也不理想,而且可能会在某些时候让您大吃一惊,那就是尽早发出对数据的请求,例如在您的应用程序初始化时,然后实际获取数据稍后的数据,比如说在需要点击 3 次才能从主页访问的页面上.手指交叉,如果星星已经对齐,那么您的http请求将在那时返回,您将拥有可以使用的数据.

The second way, which is not at all ideal, and will likely bite you on the bum at some point, is to make the request for the data early on, such as when your app is initialised, and then actually get the data later on, say on a page that requires 3 clicks to get to from the home page. Fingers crossed, if the stars have aligned, your http request will have returned by then and you will have the data to use.

angular.module('myModule').factory('myService', ['$http', '$q', function($http, $q) {
    var data = [];

    function fetch() {
        $http.get('/server/call').then(function (d) { data = d; });
    }

    // Public API
    return {
        fetchData: fetch,
        myServiceCall: function () {
            return data;
        }
    };
}]);

然后,在您模块的运行函数中,发出请求:

Then, in your module's run function, make the request:

angular.module('myModule').run(['myService', function (myService) {
    myService.fetchData();
});

然后,在保证在应用启动后至少运行 3 秒的页面的控制器中,您可以按照您的建议进行操作:

Then, in a controller for a page that is guaranteed to run at least 3 seconds after the app starts, you could do as you suggested:

 angular.module('myModule').controller('deepPageCtrl', ['$scope', 'myService', function ($scope, myService) {
      $scope.data = myService.myServiceCall();
      if (angular.isArray($scope.data) && $scope.data.length === 0) {
           panic("data isn't loaded yet");
      }
  }]);

奖励,同样糟糕的第三种方式:同步 AJAX 请求

按照 ricick 的建议去做,并使用 jQuery 的 .ajax() 方法可能的同步 AJAX 请求.

Bonus, equally bad third way: Synchronous AJAX request

Do as ricick suggests, and use the synchronous AJAX request possible with jQuery's .ajax() method.

这篇关于AngularJS $http 在服务中调用,返回解析的数据,而不是承诺的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆