AngularJS Chaining Promises不会绑定到模板

the*_*ers 1 promise angularjs

我似乎无法弄清楚为什么在使用promises后它仍然没有等待,所以$ scope.return_message返回null.

function getRandomCommit()
    {
        var d = $q.defer();
        $scope.repos = Repos.query({username: 'octocat'}).$promise.then(function ( value )
        {
            var ranNum = Math.floor((Math.random()*value.length) + 1);
            $scope.repo = Repo.get({username: 'octocat'}, {repo: value[ranNum].name}).$promise.then(function ( value2 )
            {
                $scope.commits = Commit.query({username: 'octocat'}, {repo: value2.name}).$promise.then(function ( value3 )
                {
                    var ranNum2 = Math.floor((Math.random()*value3.length));
                    d.resolve(value3[ranNum2].commit.message);
                    return d.promise;
                });
            });
        });
    };
    $scope.return_message = getRandomCommit();`
Run Code Online (Sandbox Code Playgroud)

Mic*_*zyn 6

AngularJS 1.1.x和1.0.x包含一些称为展开承诺的实验性功能.您可以将承诺传递给模板,一旦解决,模板将自动使用已解析的值而不是promise对象本身.

很酷,对吧?这可能听起来像一个很好的功能,但实际上它毕竟没那么有用.它为AngularJS添加了太多逻辑,降低了评估速度并使模板/控制器中的代码不清楚.AngularJS机组成员评论GitHub:

这个功能并没有被证明是非常有用或受欢迎的,主要是因为模板中的数据访问(作为原始值访问)和控制器代码(作为promises访问)之间的二分法.

在大多数代码中,我们最终在控制器中手动解析承诺,或者通过路由自动解决承诺并以这种方式统一模型访问.

因此,它在AngularJS 1.2.x已弃用.

您现在的选择是:

  • 等待承诺解决并设置变量 $scope
  • 强制启用展开承诺(在1.2中弃用并在1.3中删除,因此它不再是一个选项!)

要使代码工作重构getRandomCommit以返回一个promise:

function getRandomCommit () {
    var d = $q.defer();
    // your code ...
    return d.promise;
}
Run Code Online (Sandbox Code Playgroud)

并改变是什么$scope.return_message:

getRandomCommit().then(resolved_value => {
    $scope.return_message = resolved_value;
});
Run Code Online (Sandbox Code Playgroud)

如果你正在使用AngularJS 1.2,你仍然可以使用promises unwrapping,但请注意它已在1.3版中弃用并删除.您可以在AngularJS 1.0-> 1.2迁移指南中找到更多信息.

编辑(2014-10-30):

最近AngularJS 1.3发布了.在这个分支承诺中,完全删除了展开.

  • 这个答案比另一个好得多. (2认同)