AngularJS $ q承诺无法按预期工作

时间:2013-11-23 12:00:28

标签: javascript angularjs promise q

所以我似乎仍然无法正确理解承诺。下面是一个控制器,它通过资源获取一系列帖子。它应该首先获取数组,然后将数组作为单独的函数加载到作用域中。这是行不通的,因为promise中的所有函数似乎仍然被同步调用。例如,名为getPosts()的函数需要一秒钟,因为我在服务器上插入了延迟以模拟延迟。但是,尽管超过一秒钟,承诺中的所有其他功能同步调用。任何线索都会很棒。

var postController = myapp.controller('postController', function ($q, $rootScope, $scope, Post, $routeParams) {

    var new_posts = []

    $scope.new_post_count = 0

    var getPosts = function () {
        $scope.refreshing = true
        var params = $routeParams
        Post.query(params).
            $promise.then(
            function (response) {
                $scope.refreshing = false;
                new_posts = response
                $scope.new_post_count = new_posts.length - $scope.posts.length
            },
            function (response) {
                alert('Snap! ' + response.status)
            }
        )
    }

    $scope.refreshPosts = function () {
        $scope.posts = new_posts
        $scope.new_post_count = 0
    }

    /* all the functions below (marked 1, 2, 3) within the promise still called synchronously.
    I thought they would wait until the previous function has finished? */
    var defer = $q.defer()
    defer.promise
        .then(function () {
            // 1
            console.log('calling getposts')
            getPosts()
        })
        .then(function () {
            // 2
            console.log('calling refresh posts')
            $scope.refreshPosts()
        })
        .then(function () {
            // 3
            console.log('calling interval')
            $interval(function () {
                    getPosts()
                }, 7000, 0
            )
        })
    defer.resolve()

2 个答案:

答案 0 :(得分:2)

为什么不在refreshPosts的回调中呼叫getPosts。像这样:

var getPosts = function () {
        $scope.refreshing = true
        var params = $routeParams
        Post.query(params).
            $promise.then(
            function (response) {
                $scope.refreshing = false;
                new_posts = response
                $scope.new_post_count = new_posts.length - $scope.posts.length;
                $scope.refreshPosts();
            },
            function (response) {
                alert('Snap! ' + response.status)
            }
        )
    }

如果您确实需要使用代码中的.then来调用它。您需要在函数中返回一个承诺

var getPosts = function () {
        var deferred = $q.defer();
        $scope.refreshing = true;
        var params = $routeParams
        Post.query(params).
            $promise.then(
            function (response) {
                $scope.refreshing = false;
                new_posts = response
                $scope.new_post_count = new_posts.length - $scope.posts.length;

                deferred.resolve(response); //resolve deferred object 
            },
            function (response) {
                alert('Snap! ' + response.status);
                deferred.reject(response); //reject deferred object 
            }
        );
        return deferred.promise; //return a promise.
}

然后修改你的承诺链接:

function Refresh(){
    var defer = $q.defer()
    defer.promise
        .then(getPosts) //modify it here
        .then(function () {
            // 2
            console.log('calling refresh posts')
            $scope.refreshPosts();
        })
        .then(function () {
            // 3
            console.log('calling interval')
            $interval(function () {
                    Refresh()
                }, 7000, 0
            )
        })
    defer.resolve();
};

答案 1 :(得分:2)

由于$timeout也会返回promise,我们可以模拟流程。进一步,看看在promise链中我们返回下一个then(/*..*/)的承诺:

 var defer = $q.defer()
    defer.promise.then(function () {            
            console.log('calling getposts');
           return  $scope.getPosts();
        })
        .then(function (result) {
           $scope.data = result.data.results[0];   
            console.log('calling refresh posts')

            return $timeout(function () {
                   console.log('refresh posts called');
                }, 3000)
        })
        .then(function () {
            console.log('calling interval')
            $timeout(function () {
                  console.log('interval called')
                }, 3000)
        },
             function (result) {
                           alert("Error: No data returned");
                       }
              )

      defer.resolve();      

   $scope.getPosts = function () {   
      return Data.query($scope.url); 
    }   

请参阅 Fiddle 和控制台中的完整演示。

希望它会有所帮助

参考:

<强>许

  

承诺代表未来的价值,通常是未来的结果   一个异步操作,并允许我们定义什么   一旦这个值可用,或者当一个值出现时,就会发生   发生错误。

承诺链

enter image description here