Angular JS:如何绑定到promise

我正试图将一个承诺绑定到一个观点上。 我不知道你是否可以直接做到这一点,但这正是我想要做的。 任何想法我做错了什么?

注意:源代码有点过时了,并使用静态数据,但是这样可以使代码更易于诊断。

编辑: JSFiddle页面: http : //jsfiddle.net/YQwaf/27/

编辑:解决scheme:原来,你可以直接绑定承诺。 我的原始代码有两个问题:

  1. 使用setTimeout()而不是angular度的$超时是一个问题。 Angular不知道在触发超时时需要刷新UI(可以使用$ scope解决这个问题,也可以在setTimeout中使用$ apply,也可以使用$ timeout)
  2. 绑定到返回承诺的函数是一个问题。 如果第二次被调用,这又是一个承诺。 更好的办法是将范围variables设置为承诺,并根据需要创build新的承诺。 (在我的情况下,这是在国家代码中调用$ scope。$ watch)

HTML:

<div ng:controller="addressValidationController"> Region Code <select ng:model="regionCode" ng:options="r.code as r.name for r in getRegions()"/> Country Code<select ng:model="countryCode"><option value="US">United States</option><option value="CA">Canada</option></select> </div> 

JS:

 function addressValidationController($scope, $q) { var regions = { US: [{code: 'WI',name: 'Wisconsin'}, {code: 'MN',name: 'Minnesota'}], CA: [{code: 'ON',name: 'Ontario'}] }; $scope.getRegions = function () { var deferred = $q.defer(); setTimeout(function () { var countryRegions = regions[$scope.countryCode]; console.log(countryRegions); if(countryRegions === undefined) { deferred.resolve([]); } else { deferred.resolve(countryRegions); } }, 1000); return deferred.promise; }; } 

警告 :这个答案在编写时是准确的,但是从1.2开始,Angular模板引擎不能透明地处理promise。 – @Malvolio

是的,模板引擎(和expression式)透明地处理承诺,但是我将把承诺分配给控制器中的范围属性,而不是每次调用一个返回新承诺的函数(我认为这是你的问题,解决的承诺因为一个新的承诺是每次返回)。

JSFiddle: http : //jsfiddle.net/YQwaf/36/

HTML:

 <div ng:controller="addressValidationController"> Region Code <select ng:model="regionCode" ng:options="r.code as r.name for r in regions"/> Country Code<select ng:model="countryCode"><option value="US">United States</option><option value="CA">Canada</option></select> </div> 

JS:

 function addressValidationController($scope, $q, $timeout) { var regions = { US: [{ code: 'WI', name: 'Wisconsin'}, { code: 'MN', name: 'Minnesota'}], CA: [{ code: 'ON', name: 'Ontario'}] }; function getRegions(countryCode) { console.log('getRegions: ' + countryCode); var deferred = $q.defer(); $timeout(function() { var countryRegions = regions[countryCode]; if (countryRegions === undefined) { console.log('resolve empty'); deferred.resolve([]); } else { console.log('resolve'); deferred.resolve(countryRegions); } }, 1000); return deferred.promise; }; $scope.regions = []; // Manage country changes: $scope.$watch('countryCode', function(countryCode) { if (angular.isDefined(countryCode)) { $scope.regions = getRegions(countryCode); } else { $scope.regions = []; } }); }​ 

从Angular 1.2开始, 你不能直接在模板中使用promise 。
相反,你需要把结果放在$scope ,就像你平常所说的那样 – 没有魔法。

作为获取旧行为的临时解决方法,您可以调用

 $parseProvider.unwrapPromises(true) 

但是这个function稍后会被删除,所以不要依赖它。

从Angular 1.3 – $parseProvider.unwrapPromises(true) 将不再工作 。

相反,你应该直接打开承诺:

 myApiMethod().then(function(value){ $scope.item = value; }); 

请注意,承诺解包仍然可以像往常一样使用ngResource。