可以使用promises来确保在请求完成之前不使用来自AJAX请求的数据吗?

时间:2014-07-16 11:28:36

标签: javascript angularjs promise

我正在AngularJs中编写一个应用程序,我在承诺方面遇到了一些概念上的困难。更具体地说,承诺在从api中异步提取数据的作用。

当用户加载应用时,应该发生以下情况:

  1. 向api发送AJAX请求。
  2. 渲染视图。
  3. 收到来自api的回复。
  4. 处理数据。
  5. 然而,由于AJAX请求(根据定义)是异步的,因此应用程序会在服务器返回之前尝试对数据执行操作,这会导致对象出现未定义的错误等。

    我有这样的服务

    app.service('bookService', ['$http', function($http){
        var someData;
        $http.get('Some URL').success(function (data){
            someData = data.someData;
        });
    
        var bookService = {};
    
        bookService.getSomeData = function (){
            return someData;
        };
    
        return bookService;
    }]);
    

    像这样的控制器

    app.controller('BookController', ['bookService', function(bookService){
    
        console.log(bookService.getSomeData().property);
    }]);
    

    控制器会在显示附加视图后立即加载,并尝试对someData对象执行某些操作。此时它仍未定义(http请求尚未返回)发生错误。

    相反,我可能会这样做:

    app.service('bookService', ['$http', function($http){
        var someDataPromise = $http.get('Some URL');
    
        var bookService = {};
    
        bookService.getSomeData = function (){
            someDataPromise.success(function (data){
                // This should return the data contained by the promise to the caller
                // of the bookService.getSomeData function.
            });
        };
    
        return bookService;
    }]);
    

    控制器将和以前一样。

    我对promises的体验,以及整个JavaScript(尤其是回调和匿名函数等概念)的体验非常薄弱。我的怀疑是,作为概念,这可能有效,尽管可能不是我在这里展示的方式。

    承诺可以按照我在这里展示的方式使用,还是我不了解这里发生了什么?

1 个答案:

答案 0 :(得分:1)

您应该考虑更改服务以返回承诺:

app.service('bookService', ['$http', function($http){
    var bookService = {};

    bookService.getSomeData = function (){
        return $http.get('Some URL');
    });

    return bookService;
}]);

那么你的控制器也可以使用promises:

app.controller('BookController', ['bookService', '$scope', function(bookService, $scope){
    bookService.getSomeData().success(function(data) {
        $scope.data = data;
    });
}]);

您的服务通常会比检索数据更多,但希望这能证明这一概念。

值得注意的是,Angular的数据绑定会在您在范围内设置后立即获取数据。