Angular JS:如何绑定到promises

Ada*_*gen 66 promise angularjs

我试图将一个承诺绑定到一个视图.我不知道你是否可以直接这样做,但这就是我想要做的.我有什么想法我做错了吗?

注意:源有一点设计超时并使用静态数据,但这是为了使代码更容易诊断.

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

编辑:解决方案:事实证明,你可以直接绑定承诺.我的原始代码有两个问题:

  1. 使用setTimeout()而不是angular的$ timeout是一个问题.Angular不知道在触发超时时需要刷新UI(你可以用$ scope解决这个问题.$ apply在setTimeout里面,或者你可以只使用$ timeout)
  2. 绑定到返回promise的函数是一个问题.如果它第二次被召唤,它又是另一个承诺.更好的方法是将范围变量设置为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>
Run Code Online (Sandbox Code Playgroud)

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;
    };
}
Run Code Online (Sandbox Code Playgroud)

Dan*_*mov 71

从Angular 1.2开始,您不能再直接在模板中使用promises了.
相反,你需要将结果放入$scope内部then,就像你通常那样 - 没有魔力.

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

$parseProvider.unwrapPromises(true)
Run Code Online (Sandbox Code Playgroud)

但此功能稍后将被删除,因此请不要依赖它.

  • 及时有用的答案!我刚刚从Angular的旧版本的教程中勉强结束. (5认同)

Gui*_*e86 29

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

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

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>
Run Code Online (Sandbox Code Playgroud)

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 = [];
        }
    });
}?
Run Code Online (Sandbox Code Playgroud)

  • **警告**:这个答案在编写时是准确的,但从1.2开始[Angular模板引擎不能透明地处理承诺](https://github.com/angular/angular.js/commit/5dc35b527b3c99f6544b8cb52e93c6510d3ac577)! (24认同)

Ben*_*aum 27

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

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

myApiMethod().then(function(value){
    $scope.item = value; 
});
Run Code Online (Sandbox Code Playgroud)

请注意,承诺展开仍然可以像往常一样使用ngResource.

  • @RyanWeiss它不是特定于`$ http`它特定于使用Angular承诺($ q)创建的承诺.如果你想要你的$ .ajax那么你可以通过`$ q.when(yourPromise)`把它转换为一个.无论如何,最好在http中使用$ http作为http请求. (8认同)
  • 嗯,不完全是,但摘要将自动应用于IF并且仅当您使用$ http方法(具有执行该操作的特殊处理程序)时.我最初使用的是jQuery的$ .ajax方法,这就是为什么当我在promise返回后更改范围时它无法正常工作.更改它以使用Angular的$ http解决了这个问题.谢谢本杰明. (3认同)
  • 这应该是新接受的答案 (3认同)