Angular JS:在向用户显示视图之前从服务器获取数据

时间:2014-05-19 06:44:30

标签: angularjs promise angularjs-service

我的config如下所示:

app.config(function ($routeProvider) {
    $routeProvider
        ...
        .when('/project/:slug', {
            templateUrl: 'partials/plaintasks-part.php',
            controller: 'ProjectCtrl',
            resolve : {
                projectDetail : ProjectCtrl.loadProject
            }
        })
        ...
});

loadProject如下:

// Project controller
var ProjectCtrl = app.controller('ProjectCtrl', ...);

ProjectCtrl.loadProject = function( $q, Tasks, $route ){

    var defer = $q.defer();

    var slug = $route.current.params.slug;
    // Tasks.getProjectBySlug() is where I have implemented the http request to get the data from server
    var project = Tasks.getProjectBySlug( slug );
    var tasks = Tasks.getProjectTasks( project.id );

    defer.resolve({ 
        tasks : tasks,
        project : project
    });

    return defer.promise;
}

现在的问题是,它不会等待从服务器提取projectstasks,只是显示我不想要的视图,除非数据从服务器获取。任何人都可以告诉我,我在这里做错了什么?尽管我在路线中实施了resolve,为什么不等待提取数据呢?

2 个答案:

答案 0 :(得分:1)

问题在于您的实施。您没有正确解决延迟问题。我认为Task方法都会返回承诺,你需要做这样的事情

Tasks.getProjectBySlug(slug).then(function(project) {
   Tasks.getProjectTasks( project.id ).then (function(tasks) {
      defer.resolve({ 
        tasks : tasks,
        project : project
      });
   })     
});

答案 1 :(得分:1)

您的代码有两个问题:

  • 你有一个超额延期(不需要那个$ q.defer()那里,它是deferred anti pattern
  • 当您解决延迟时,您不会等待承诺解决。

由于getProjectTasks根据问题是一个HTTP调用,因此除非有可能发出HTTP请求,否则它不应返回一个promise。如果它发出HTTP请求 - 请在你的后端写一个方法来获取一个slug并返回项目它的任务,因为两次往返的开销非常昂贵。

然后,您可以将loadProject减少为:

ProjectCtrl.loadProject = function( $q, Tasks, $route ){
     return Task.getProjectBySlug($route.current.params.slug).then(function(project){
          return {tasks:Tasks.getProjectTasks(project.id), project: project};
     });
};

如果您绝对必须进行两次通话,您仍然可以:

ProjectCtrl.loadProject = function( $q, Tasks, $route ){  
    var getProject = Task.getProjectBySlug($route.current.params.slug);
    var getTasks = p.then(function(project){ return Tasks.getProjectTasks(project.id);});
    return $q.all([getTasks,getProject]).then(function(project,tasks){
         return {tasks:tasks,project:project};
    });
}

仍然可以避免嵌套。