如何在调用服务中的方法之前异步执行某些代码?

时间:2021-08-11 07:39:37

I am having some problems with executing some tasks before my service is initialised and it's methods used. Some context:

在我的服务初始化之前执行某些任务时遇到了一些问题,并且使用了它的方法。一些背景:

I am producing an application which uses REST to communicate with 2 different backend systems (the reason for this is that if our client upgrades in the future it will still work). These backend systems have slightly different paths for the same REST calls.

我正在生产一个使用REST与2个不同的后端系统进行通信的应用程序(原因是如果我们的客户端将来升级它仍然可以工作)。这些后端系统对于相同的REST调用具有略微不同的路径。

To know which calls to use I thought a solution might be to call one test endpoint which exists in one, but not the other, and depending on the response code received, set a variable which is the beginning of the URL. e.g. /rest/services/StartpointService/.

要知道使用哪个调用我认为解决方案可能是调用一个存在于一个测试端点而不是另一个测试端点的测试端点,并根据收到的响应代码设置一个变量,该变量是URL的开头。例如/ REST /服务/ StartpointService /。

All the REST calls are in a single factory and I tried something like this:

所有REST调用都在一个工厂中,我尝试过这样的事情:

angular.module('myApp.services', [])
.factory('myServices', [
    '$http',
    '$q',
    function($http, $q) {

        //test function, if success we are using 1 backend, if fails, we use the other
        var loginTest = function() {

            var deferred = $q.defer();

            $http( {

                method: 'POST',
                url: '/um/login?um_no_redirect=true'

            })
            .success(function(data, status, headers, config) {

                deferred.resolve(status);

            })
            .error(function(data, status, headers, config) {

                deferred.reject(status);

            });
            return deferred.promise;

        };


        var url;

        loginTest()
        .then( function(response) { //if backend1

            if(responseCode === 200) {
                url = '/rest/services/etc/etc' //set the URL
            }

        },
        function(errorCode) {   //If backend2


            if(errorCode === 404) {

                url = '/LCConnector/rest/services/etc/etc';

            }

        });



        var service = {

            realCall : function() {

                                    //use 'url' variable in the $http call

                            }
                    }

                    return service;

           }]);

Obviously as the loginTest is asyncronous, the service is injected into my controller and is called before url is set.

显然,当loginTest是异步时,服务被注入我的控制器并在设置url之前被调用。

I have looked into running in a config or run block when the app is first initialised but can't quite understand how to get the variable out.

我已经考虑在首次初始化应用程序时运行配置或运行块,但不能完全理解如何获取变量。

If i can give anything further details, please let me know!

如果我能提供更多详情,请告诉我!

Regards,

Augier

2 个解决方案

#1


2  

If this check is required before the application is initialized you can manually bootstrap your application after the Ajax call. Inside of your fail() or done() call backs you can alter the module config to reflect the url you need. From there you can easily inject your config into any service that requires this url.

如果在初始化应用程序之前需要进行此检查,则可以在Ajax调用之后手动引导应用程序。在fail()或done()回调内部,您可以更改模块配置以反映您需要的URL。从那里,您可以轻松地将配置注入任何需要此URL的服务。

example on jsfiddle

<div ng-controller="MyCtrl">{{url}}</div>


//if you chanée this url to /echo/fail and url will now be url1
var urlToCheck = '/echo/json/';

var myApp = angular.module('myApp', []);

myApp.controller("MyCtrl", ["$scope", "config", function ($scope, config) {
    $scope.url = config.url;
}]);

$.ajax({
    url: urlToCheck
}).fail(function () {
    myApp.constant('config', {
        url: '/fail-url'
    });
}).done(function () {
    myApp.constant('config', {
        url: '/done-url'
    });
}).always(function () {
    angular.bootstrap(document, ['myApp']);
});

#2


0  

You could take advantage of $routeProvider, which allows you to delay your controller instantiation until your promise has been resolved.

您可以利用$ routeProvider,它允许您延迟控制器实例化,直到您的承诺得到解决。

$routeProvider exposes a method called resolve for that purpose. See the AngularJS doc:

$ routeProvider为此目的公开了一个名为resolve的方法。请参阅AngularJS文档:

http://docs.angularjs.org/api/ngRoute.$routeProvider

Additional information in this excellent SO question:

这个优秀的SO问题中的其他信息:

AngularJS : Initialize service with asynchronous data

AngularJS:使用异步数据初始化服务

Highly recommended.

#1


2  

If this check is required before the application is initialized you can manually bootstrap your application after the Ajax call. Inside of your fail() or done() call backs you can alter the module config to reflect the url you need. From there you can easily inject your config into any service that requires this url.

如果在初始化应用程序之前需要进行此检查,则可以在Ajax调用之后手动引导应用程序。在fail()或done()回调内部,您可以更改模块配置以反映您需要的URL。从那里,您可以轻松地将配置注入任何需要此URL的服务。

example on jsfiddle

<div ng-controller="MyCtrl">{{url}}</div>


//if you chanée this url to /echo/fail and url will now be url1
var urlToCheck = '/echo/json/';

var myApp = angular.module('myApp', []);

myApp.controller("MyCtrl", ["$scope", "config", function ($scope, config) {
    $scope.url = config.url;
}]);

$.ajax({
    url: urlToCheck
}).fail(function () {
    myApp.constant('config', {
        url: '/fail-url'
    });
}).done(function () {
    myApp.constant('config', {
        url: '/done-url'
    });
}).always(function () {
    angular.bootstrap(document, ['myApp']);
});

#2


0  

You could take advantage of $routeProvider, which allows you to delay your controller instantiation until your promise has been resolved.

您可以利用$ routeProvider,它允许您延迟控制器实例化,直到您的承诺得到解决。

$routeProvider exposes a method called resolve for that purpose. See the AngularJS doc:

$ routeProvider为此目的公开了一个名为resolve的方法。请参阅AngularJS文档:

http://docs.angularjs.org/api/ngRoute.$routeProvider

Additional information in this excellent SO question:

这个优秀的SO问题中的其他信息:

AngularJS : Initialize service with asynchronous data

AngularJS:使用异步数据初始化服务

Highly recommended.