问题
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