我正试图让异步工作在角度,但它还没有完成工作。但差不多。
我试图将我的代码压缩到最低限度:
<div ng-controller="GeoSelectController">
<div>
Select country:<br/>
<select multiple required size="10" ng-model="geoFilter" ng-options="geo.name as geo.descr for geo in geos"></select>
<p>You selected {{geoFilter}}.</p>
</div>
</div>
<script type="text/javascript" src="js/vendor/jQuery/jquery-2.1.1"></script>
<script type="text/javascript" src="js/vendor/angular/angular.min.js"></script>
<script type="text/javascript" src="js/customModule.js"></script>
<script type="text/javascript">
var app = angular.module("myApp", []);
var cm = customModule();
app.controller("GeoSelectController", function ($scope) {
//some starting values.
$scope.geos = [
{name: "DE", descr: "Germany"},
{name: "NL", descr: "Netherlands"}
];
$scope.geoFilter = ["NL"];
//asynchronously get actual values.
cm.doAsync("nrg_100a", function(error){
if (error) {alert(error); return;}
$scope.geos = cm.getSomeData("nrg_100a", "GEO");
});
});
</script>
这里的问题是cm.doAsync()
部分。发生的情况是geos
变量 已更新,但它未在视图中显示,直到单击选择框。我录制了一个截屏视频,以澄清:
(如果我点击已选择的'荷兰',则选择框的选项甚至都不会更新。)
我已经尝试将整件物品放入工厂内,但无济于事,我认为这也不是必要的。如果你认为这是关键,那么请解释为什么会这样;我非常乐意发布也失败的代码。
谢谢你们!
答案 0 :(得分:2)
很可能是因为doAsync
没有在角度范围内运行。工作完成后,意义digest
周期没有发生。您可以使用$scope.apply()
手动强制摘要周期并更新绑定来解决此问题。
cm.doAsync("nrg_100a", function(error){
if (error) {alert(error); return;}
$scope.geos = cm.getSomeData("nrg_100a", "GEO");
$scope.$apply(); //<--- here
});
如果它正在执行异步操作(并且您可以更改自定义模块),则可以使用$q
的角度版本来使用promise模式,并且您不需要执行此步骤。如果您正在进行http调用,可以使用$http
并通过promise进行链接,并且一旦解析/拒绝承诺,绑定将自动更新。
创建一个服务以包装您的非角度服务: -
MyService.$inject = ['$q', '$window'];
function MyService($q, $window){
this.getGeos = function(value1, value2) {
var def= $q.defer();
var cm = $window.customModule();
cm.doAsync(value, function(error){
if (error) {
def.reject(error); //<-- reject the promise
}
var value = cm.getSomeData(value1, value2);
def.resolve(value);
});
return def.promise;
}
}
angular.module("myApp").service('MyService', MyService);
并将其用作: -
app.controller("GeoSelectController", ['$scope', 'MyService',function ($scope, myService) {
//some starting values.
$scope.geos = [
{name: "DE", descr: "Germany"},
{name: "NL", descr: "Netherlands"}
];
$scope.geoFilter = ["NL"];
myService.getGeos("nrg_100a", "GEO").then(function(result){
$scope.geos = result; //set the result
}).catch(function(error){
alert(error); //Handle Error
})
}]);