AngularJs:如何结合表单输入作为URL参数使用Factory获取数据?
你遇到的fourSquareService.getVenues is not a function错误,主要是两个细节问题导致的,咱们一步步来梳理解决:
1. 控制器依赖注入顺序不匹配
AngularJS的依赖注入是严格按数组声明顺序和函数参数顺序一一对应的。你看控制器的注入代码:
app.controller('MainController', ['$scope', 'apixuService', 'fourSquareService', function ($scope, fourSquareService, apixuService) {
数组里的顺序是[$scope, apixuService, fourSquareService],但函数参数却写成了($scope, fourSquareService, apixuService)——这就导致fourSquareService变量实际拿到的是apixuService的实例,而apixuService拿到的是fourSquareService的实例。自然调用fourSquareService.getVenues会报错,因为apixuService里根本没有这个方法!
2. 错误使用未定义的getWeather变量
在控制器调用天气接口时,你写的是getWeather.getCurrentWeather()和getWeather.getForecast(),但你注入的服务是apixuService,根本没定义getWeather这个变量,这部分也会触发报错。
修正后的控制器代码
把依赖顺序调整正确,同时把getWeather替换成注入的apixuService:
app.controller('MainController', ['$scope', 'apixuService', 'fourSquareService', function ($scope, apixuService, fourSquareService) { //Search on Click Function $scope.executeSearch = function () { //Venues fourSquareService.getVenues($scope.cityInput).then(function (response) { $scope.fouSquareData = response.data.response $scope.destination = $scope.fouSquareData.geocode.displayString; $scope.venues = $scope.fouSquareData.groups[0].items.map(spot => spot.venue); let photos = []; $scope.venues.forEach((venue, index) => venue.photos.groups[0] && venue.url ? photos.push(`<a href="${venue.url}" target="_blank"><img class="venueimg" src="${imgPrefix}${venue.photos.groups[0].items[0].suffix}"/></a>`) : venue.photos.groups[0] ? photos.push(`<img class="venueimg" src="${imgPrefix}${venue.photos.groups[0].items[0].suffix}"/>`) : photos.push('<img class="venueimg" src="./img/320px-No_image_available.png"/>') ); $scope.photos = photos; }, function (error) { $scope.showdestination = true; $scope.showData = false; $scope.destination = 'Place not found, please try again.'; }); //Current Weather apixuService.getCurrentWeather($scope.cityInput).then(function (response) { $scope.currentWeather = response.data.current; $scope.place = response.data.location.name; }); //Forecast apixuService.getForecast($scope.cityInput).then(function (response) { $scope.showdestination = true; $scope.showData = true; $scope.forecast = response.data.forecast.forecastday; const weekDays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']; $scope.weekDays = []; $scope.forecast.forEach(function (day, index) { $scope.weekDays[index] = weekDays[(new Date(day.date)).getDay()] }); $scope.weekDays[0] = 'Today'; $scope.weekDays[1] = 'Tomorrow'; }); }; }]);
额外小提醒
你在Foursquare服务里定义的imgPrefix是服务内部的局部变量,控制器里直接引用会找不到。可以把它加到服务的返回对象里,让控制器能正常调用:
app.factory('fourSquareService', ['$http', function ($http) { // ... 其他原有代码 ... return { getVenues: function(place) { /* ... 原有逻辑 ... */ }, imgPrefix: imgPrefix // 将图片前缀暴露给外部 } }]);
之后在控制器里通过fourSquareService.imgPrefix来引用这个变量,就不会出现变量未定义的问题了。
内容的提问来源于stack exchange,提问作者Pedro Santos

