What's the best way to pass “$routeParams” to a Service in AngularJS?

心不动则不痛 提交于 2019-12-24 06:47:11

问题


In my angularJs app I'm able to get $routeParams in the controller but how should I get it in a service? I would like to follow the separation of concerns approach and keep my http requests separate from my controllers.

I've tried the below in my app.js but I get a Error: $injector:unpr Unknown Provider

var app = angular.module('app', ['ngRoute']);  // TODO: 'ngAnimate', 'ui.bootstrap' 

app.config(['$routeProvider','$locationProvider', function($routeProvider, $locationProvider){

    $routeProvider
        .when('/', {
            templateUrl: '/app/static/home.html',
            controller: 'mainController as mainCtrl'

        })
        .when('/match/id-:matchId', {
            templateUrl: '/app/components/match/matchView.html',
            controller: 'matchController as matchCtrl'
        });

    // use the HTML5 History API
    $locationProvider.html5Mode(true);
}]);

app.controller('matchController', ['$routeParams', 'matchService', function ($routeParams, matchService) {
    var matchCtrl = this;
    matchCtrl.matchId = $routeParams..matchId;  // how can I move this into the service

    this.getMatchId = function ()
    {
        return matchCtrl.matchId;
    };

    var promise = matchService.getMatch();
    promise.then(function (data)
    {
        matchCtrl.match = data;
    });
}])

app.service("matchService", function ($http, $q, matchController)
{
    var matchId = matchController.getTable();

    var url = 'https://jsonplaceholder.typicode.com/posts/1';
    $http({
        method: 'GET',
        cache: true,
        url: url,
        headers: {  
           'Content-Type': 'application/json;charset=UTF-8'  
        }
    }).
    success(function(response) {
        //your code when success
        // lgTblCtrl.amateurTable = data;
        deferred.resolve(response);
        console.log('SUCCESS!');
    }).
    error(function(response) {
        //your code when fails
        console.log('ERROR!');
    });

    this.getTable = function ()
    {
        return deferred.promise;
    };
})

回答1:


First of all, you have created cyclic reference where the matchService is injected into the matchController and matchController is injected into the matchService.

Service is a singleton object, created once which is the same instance passed wherever it gets injected. On contrast, controller will be created one per view. So if you have two views using the same controller, separate controller instances will be created and used by them by not sharing the $scope. So, if you inject a controller to the service, again another instance will be created and injected to the service.

Since a service should be generic and independent of the controller, you should not inject controller to any service as per the best coding practice.

Also, as a service is singleton and can be used by any controller or view, it should be independent to the view/route and hence you can't use $routeParams inside the service.

Instead, you can pass the $routeParams.matchId as an argument to the service method.

Note: In your controller, you have used $routeParams..matchId with double dots (..) instead of $routeParams.matchId.

Also, there is no matchService.getMatch inside the matchService which used by the controller.

You have to correct them.

I have changed the code below as I explained and have a look.

var app = angular.module('app', ['ngRoute']);  // TODO: 'ngAnimate', 'ui.bootstrap' 

app.config(['$routeProvider','$locationProvider', function($routeProvider, $locationProvider){

    $routeProvider
        .when('/', {
            templateUrl: '/app/static/home.html',
            controller: 'mainController as mainCtrl'

        })
        .when('/match/id-:matchId', {
            templateUrl: '/app/components/match/matchView.html',
            controller: 'matchController as matchCtrl'
        });

    // use the HTML5 History API
    $locationProvider.html5Mode(true);
}]);

app.controller('matchController', ['$routeParams', 'matchService', function ($routeParams, matchService) {
    var matchCtrl = {};

    var promise = matchService.getMatch($routeParams.matchId);
    promise.then(function (data)
    {
        matchCtrl.match = data;
    });
}])

app.service("matchService", function ($http, $q)
{
    var deferred = $q.defer();

    function getMatch(matchId) {
      var url = 'https://jsonplaceholder.typicode.com/posts/1';
      return $http({
        method: 'GET',
        cache: true,
        url: url,
        headers: {  
           'Content-Type': 'application/json;charset=UTF-8'  
        }
      }).
      then(function(response) {
        //your code when success
        // lgTblCtrl.amateurTable = data;
        deferred.resolve(response);
        console.log('SUCCESS!');
      }, function(response) {
        //your code when fails
        console.log('ERROR!');
        deferred.reject(response);
      });

      return deferred.promise;
    }

    this.getMatch = getMatch;
})


来源:https://stackoverflow.com/questions/41030456/whats-the-best-way-to-pass-routeparams-to-a-service-in-angularjs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!