68

我正在尝试将承诺绑定到视图。我不知道你是否可以直接这样做,但这就是我正在尝试做的。任何想法我做错了什么?

注意:源有点做作超时并使用静态数据,但这是为了使代码更易于诊断。

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

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

  1. 使用 setTimeout() 而不是 angular 的 $timeout 是一个问题。Angular 不知道它需要在触发超时时刷新 UI(你可以在 setTimeout 中使用 $scope.$apply 来解决这个问题,或者你可以只使用 $timeout )
  2. 绑定到返回承诺的函数是一个问题。如果它被第二次调用,它会做出另一个承诺。更好的是为 promise 设置一个范围变量,并且只根据需要创建一个新的 promise。(就我而言,这是在国家代码上调用 $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;
    };
}
4

4 回答 4

70

从 Angular 1.2 开始,你不能再直接在模板中使用 Promise 了。相反,您需要像往常一样将
结果放入$scopeinside ——没有魔法。then

作为获得旧行为的临时解决方法,您可以致电

$parseProvider.unwrapPromises(true)

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

于 2014-01-24T17:36:18.157 回答
29

警告:这个答案在编写时是准确的,但是从 1.2 开始,Angular 模板引擎不能透明地处理承诺!-- @马伏里奥

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

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 = [];
        }
    });
}​
于 2012-10-23T15:23:24.990 回答
27

从 Angular 1.3 开始 -$parseProvider.unwrapPromises(true) 将不再工作

相反,您应该直接解开 Promise:

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

请注意,promise unwrapping 仍然可以像往常一样与 ngResource 一起使用。

于 2014-09-14T19:11:48.107 回答
0

返回对保存列表的范围变量的引用就足够了。

function addressValidationController($scope,$timeout) {
    var regions = {
        US: [{code: 'WI',name: 'Wisconsin'}, {code: 'MN',name: 'Minnesota'}], 
        CA: [{code: 'ON',name: 'Ontario'}]
    };

    $scope._regions = [];

    $scope.getRegions = function () {

        $timeout(function () {
            var countryRegions = regions[$scope.countryCode];
            console.log(countryRegions);
            if(countryRegions === undefined) {
                $scope._regions = []
            } else {
                $scope._regions = countryRegions
            }
        }, 1000);

        return $scope._regions;
    };
}
于 2018-05-20T23:46:14.977 回答