我正在努力将一些JSON请求从控制器中分离出来并转换为角度的工厂服务,并使其正常工作。目前,当我更新数据时(与新数据的请求一样),我必须提出两次请求以实际查看更新的数据。我认为,从我目前对Angular的有限知识来看,我错过了承诺方面。但是,我不确定如何最好地继续下去。代码如下:
(function(angular) {
'use strict';
var myApp = angular.module('weatherApp', [])
.controller('MyWeatherController', ['$scope', '$http', '$log', 'weather', function($scope, $http, $log, weather) {
$scope.city = 'Cincinnati';
$scope.units = 'imperial';
$scope.updateData = function() {
weather.updateData($scope, $http, $log);
};
// Initial run to fetch weather data
$scope.updateData();
}])
// Set up a service factory to fetch current and forecast data
.factory('weather', ['$http', function($http) {
var services = {};
services.updateData = function(scope, http, log) {
this.updateCurrent(scope, http, log);
}
// Get current data
services.updateCurrent = function(scope, http, log) {
// Fetch current weather data from api
var url = 'http://api.openweathermap.org/data/2.5/weather';
http.jsonp(url, {params: {
q: scope.city,
units: scope.units,
callback: 'JSON_CALLBACK'
}})
.success(function(data, status, headers, config) {
scope.main = data.main;
scope.wind = data.wind;
scope.description = data.weather[0].description;
})
.error(function(data, status, headers, config) {
log.error('Could not retrieve data from '+url);
});
};
return services;
}]);
} (window.angular));
body {
width: 50%;
margin: 2em auto;
}
h2 {
background: green;
color: white;
padding: 10px;
margin-bottom: 0;
}
input {
margin-bottom: 1em;
}
.section {
margin-bottom: 2em;
background: #f0f0f0;
padding: 10px;
}
<!DOCTYPE html>
<html>
<head>
<title>Weather checker</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.11/angular.min.js"></script>
<script src="script.js"></script>
<link type="text/css" rel="stylesheet" href="style.css" media="all" />
</head>
<body>
<div class="container" ng-app="weatherApp">
<div ng-controller="MyWeatherController">
<h2>Current weather in {{city}}</h2>
<div class="section current">
<form name="weather-form">
<label for="city">City, State / Zip code</label>
<input
type="text"
ng-model="city"
ng-model-options="{updateOn: 'submit'}">
<br>
<label for="units">Units</label>
<input type="radio" ng-model="units" value="metric"> Metric
<input type="radio" ng-model="units" value="imperial"> Imperial<br>
<button ng-click="updateData()">Update</button>
<h3>{{data.name}}</h3>
<p>{{description}}</p>
<p>Temperature: {{main.temp}}</p>
<p>Wind speed: {{wind.speed}}</p>
</form>
</div>
</div>
</div>
</body>
</html>
如您所知,如果您运行此操作,则必须更新两次以获取要在视图中显示的新数据。对于某些示例的任何建议或对后续步骤的反馈将不胜感激!
由于
答案 0 :(得分:1)
这是承诺的实施。
你的承诺代码看起来像这样,你不应该像$ scope,$ http,$ log这样的变量传递给服务,它们将通过注入依赖项在服务中轻松获得。
scope
变量不应该使用服务进行修改,您应该从服务返回一个承诺,并且在promise成功或错误内部,您可以修改范围。
从服务我返回已经有承诺的$http.jsonp
,所以你不需要关心返回promise,并且这个promise在.success
函数内得到解决,你可以在{{1}内获得拒绝承诺功能
<强> CODE 强>
.error
希望这对你有所帮助,谢谢。
答案 1 :(得分:1)
这是因为ng-model-options
指令。
在我们提交表单之前,模型中的城市值不会更新。
因此,在更改城市后,当我们第一次点击时,将为旧城市提取值,这不会反映用户界面中的任何更改。由于这是提交操作,因此将更新模型。
当我们第二次点击时,会使用新的城市值获取值。
答案 2 :(得分:0)
(function(angular) {
'use strict';
var myApp = angular.module('weatherApp', [])
.controller('MyWeatherController', ['$scope', '$http', '$log', 'weather', function($scope, $http, $log, weather) {
$scope.city = 'Cincinnati';
$scope.units = 'imperial';
$scope.updateData = function() {
weather.updateData($scope, $http, $log);
};
// Initial run to fetch weather data
$scope.updateData();
}])
// Set up a service factory to fetch current and forecast data
.factory('weather', ['$http', function($http) {
var services = {};
services.updateData = function(scope, http, log) {
this.updateCurrent(scope, http, log);
}
// Get current data
services.updateCurrent = function(scope, http, log) {
// Fetch current weather data from api
var url = 'http://api.openweathermap.org/data/2.5/weather';
http.jsonp(url, {params: {
q: scope.city,
units: scope.units,
callback: 'JSON_CALLBACK'
}})
.success(function(data, status, headers, config) {
scope.main = data.main;
scope.wind = data.wind;
scope.description = data.weather[0].description;
$scope.digest();
})
.error(function(data, status, headers, config) {
log.error('Could not retrieve data from '+url);
});
};
return services;
}]);
} (window.angular));
body {
width: 50%;
margin: 2em auto;
}
h2 {
background: green;
color: white;
padding: 10px;
margin-bottom: 0;
}
input {
margin-bottom: 1em;
}
.section {
margin-bottom: 2em;
background: #f0f0f0;
padding: 10px;
}
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" version="XHTML+RDFa 1.0">
<head>
<title>Weather checker</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.11/angular.min.js"></script>
<script src="script.js"></script>
<link type="text/css" rel="stylesheet" href="style.css" media="all" />
</head>
<body>
<div class="container" ng-app="weatherApp">
<div ng-controller="MyWeatherController">
<h2>Current weather in {{city}}</h2>
<div class="section current">
<form name="weather-form">
<label for="city">City, State / Zip code</label>
<input
type="text"
ng-model="city"
ng-model-options="{updateOn: 'submit'}">
<br>
<label for="units">Units</label>
<input type="radio" ng-model="units" value="metric"> Metric
<input type="radio" ng-model="units" value="imperial"> Imperial<br>
<button ng-click="updateData()">Update</button>
<h3>{{data.name}}</h3>
<p>{{description}}</p>
<p>Temperature: {{main.temp}}</p>
<p>Wind speed: {{wind.speed}}</p>
</form>
</div>
</div>
</div>
</body>
</html>
答案 3 :(得分:0)
你有两种方式(好吧,可能还有更多)你可以去这里。 您可以创建一个promise并返回从promise中的http调用返回的数据,以便在控制器中解析。查看$ q here文档的第二个代码块,了解如何执行此操作。
但是,我建议您在服务中创建一个公共属性来保存数据。然后,您可以从控制器访问它。由于Angular的数据绑定,当服务器响应最终返回并且数据存储在服务中时,控制器将自动地&#34;参见&#34;更新后的价值。
(function(angular) {
'use strict';
var myApp = angular.module('weatherApp', [])
.controller('MyWeatherController', ['$scope', '$http', '$log', 'weather', function($scope, $http, $log, weather) {
//here you expose the service to your scope. From here you can
//get at all your data in the view by using weather.result
$scope.weather = weather;
$scope.city = 'Cincinnati';
$scope.units = 'imperial';
$scope.updateData = function() {
weather.updateData($scope, $http, $log);
};
// Initial run to fetch weather data
$scope.updateData();
}])
// Set up a service factory to fetch current and forecast data
.factory('weather', ['$http', function($http) {
var services = {};
//make the server response data part of the service's public API
services.details = {
someDetail: "",
someOtherThing: []
}
services.updateData = function(scope, http, log) {
this.updateCurrent(scope, http, log);
}
// Get current data
services.updateCurrent = function(scope, http, log) {
// Fetch current weather data from api
var url = 'http://api.openweathermap.org/data/2.5/weather';
http.jsonp(url, {params: {
q: scope.city,
units: scope.units,
callback: 'JSON_CALLBACK'
}})
.success(function(data, status, headers, config) {
//here we assign the data to the service's result property.
services.details.someDetail = data.someDetail;
services.details.someOtherThing = data.someOtherThing;
})
.error(function(data, status, headers, config) {
log.error('Could not retrieve data from '+url);
});
};
return services;
}]);
} (window.angular));
&#13;
<p>Some detail:{{weather.details.someDetail}}</p>
<p>Some other thing: {{weather.details.someOTherThing}}</p>
&#13;
答案 4 :(得分:0)
我从你的html中删除了ng-model-options="{updateOn: 'submit'}
并且它运行良好:)
(function(angular) {
'use strict';
var myApp = angular.module('weatherApp', [])
.controller('MyWeatherController', ['$scope', '$http', '$log', 'weather', function($scope, $http, $log, weather) {
$scope.city = 'Cincinnati';
$scope.units = 'imperial';
$scope.updateData = function() {
weather.updateData($scope, $http, $log);
};
// Initial run to fetch weather data
$scope.updateData();
}])
// Set up a service factory to fetch current and forecast data
.factory('weather', ['$http', function($http) {
var services = {};
services.updateData = function(scope, http, log) {
this.updateCurrent(scope, http, log);
}
// Get current data
services.updateCurrent = function(scope, http, log) {
// Fetch current weather data from api
var url = 'http://api.openweathermap.org/data/2.5/weather';
http.jsonp(url, {params: {
q: scope.city,
units: scope.units,
callback: 'JSON_CALLBACK'
}})
.success(function(data, status, headers, config) {
scope.main = data.main;
scope.wind = data.wind;
scope.description = data.weather[0].description;
})
.error(function(data, status, headers, config) {
log.error('Could not retrieve data from '+url);
});
};
return services;
}]);
} (window.angular));
body {
width: 50%;
margin: 2em auto;
}
h2 {
background: green;
color: white;
padding: 10px;
margin-bottom: 0;
}
input {
margin-bottom: 1em;
}
.section {
margin-bottom: 2em;
background: #f0f0f0;
padding: 10px;
}
<!DOCTYPE html>
<html>
<head>
<title>Weather checker</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.11/angular.min.js"></script>
<script src="script.js"></script>
<link type="text/css" rel="stylesheet" href="style.css" media="all" />
</head>
<body>
<div class="container" ng-app="weatherApp">
<div ng-controller="MyWeatherController">
<h2>Current weather in {{city}}</h2>
<div class="section current">
<form name="weather-form">
<label for="city">City, State / Zip code</label>
<input
type="text"
ng-model="city">
<br>
<label for="units">Units</label>
<input type="radio" ng-model="units" value="metric"> Metric
<input type="radio" ng-model="units" value="imperial"> Imperial<br>
<button ng-click="updateData()">Update</button>
<h3>{{data.name}}</h3>
<p>{{description}}</p>
<p>Temperature: {{main.temp}}</p>
<p>Wind speed: {{wind.speed}}</p>
</form>
</div>
</div>
</div>
</body>
</html>