【问题标题】:AngularJS $q promises not working as expectedAngularJS $q 承诺不能按预期工作
【发布时间】:2013-11-23 21:00:19
【问题描述】:

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

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()

【问题讨论】:

  • all the functions in the promise still seems to get called synchronously. all the functions 是什么?谢谢
  • 我试图澄清这个问题。我希望它现在更有意义

标签: javascript angularjs promise q


【解决方案1】:

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

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();
};

【讨论】:

    【解决方案2】:

    由于$timeout 也返回了promise,我们可以模拟流程。此外,看看在 Promise 链中,我们为下一个 then(/*..*/) 返回 Promise:

     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 和控制台中查看完整的演示。

    希望对你有帮助

    参考资料:

    承诺

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

    承诺链

    【讨论】:

    • +1 参考部分对我有帮助。我没有在第一个.then 中将返回的数据传递给函数(数据)调用。呃。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-05
    • 2018-09-19
    • 1970-01-01
    • 1970-01-01
    • 2019-12-03
    • 2019-01-19
    • 1970-01-01
    相关资源
    最近更新 更多