Controller 之后的服务 运行? returns 未定义

Service run after Controller? returns undefined

我正在将 json 数据加载到我的应用程序中,但它总是 return 未定义。 经过多次测试和更改后,我发现该服务在控制器之后运行,或者至少我认为是这样。

服务

.factory('personService', function($http) {
    return {
        getPersons: function() {
            return $http.get('/persons.php');
        }
    }
})

控制器

.controller('personsCtrl', function($scope, personService) {
   var promise = personService.getPersons();
   promise.then(
      function(response) { 
        $scope.persons = response.data;
          console.log(response.data);//first
      },
      function(response) {
          console.log('failed loading');
      });

    console.log($scope.persons); //last
})

控制台在 //first 之前打印出 //last,这意味着它可能在从 json 文件获取数据之前运行。

控制台

undefined
[object object object]

有人知道我在这里做错了什么吗?谢谢。

这就是它的工作方式。你为什么担心 "console.log($scope.persons); //last" 你需要在控制器中获取数据,你正在获取它。在 $http 调用之后,您的 $scope.person 正在更新,这将依次更新您的视图。

您如何确定 "console.log($scope.persons);" 比“ console.log(response.data);”先执行?

尝试如下修改您的服务。

.factory('personService', function($http) {

var getPersons= function() {

    return $http.get('/persons.php').then(function(result){
        return result.data;
    });
};
return { getPersons: getPersons};
});

您的代码非常好,无需更改。

我不会听从 Vamsi 的建议 - 对不起,伙计 - 因为在控制器中解决承诺总是比立即解决它更好。

这样做的原因是在某些时候您可能希望将它 (getPersons) 与来自其他服务的其他承诺链接起来:

personService.getPersons()
    .then(function(result){
        return service2.doSomething(result);
    })
    .then(function(result){
        return service3.doSomeOtherThing(result);
    })
    .then(function(result){
        return service4.doLastThing(result);
    })
    .catch(function (reason) {
        console.log(reason);
    })
    .finally(function(){
        // always executed.
    }); 

如果您查看这段代码,您会看到一个典型的承诺链,其中每个服务都使用前一个承诺的结果,然后 returns 它到链的下一个分支。

如果发生错误,您可以catch 错误并继续。

回到你的问题:

.controller('personsCtrl', function($scope, personService) {
   var promise = personService.getPersons();
   promise.then(
      function(response) { 
        $scope.persons = response.data;
          console.log(response.data);//first
      },
      function(response) {
          console.log('failed loading');
      });

    console.log($scope.persons); //last
});

承诺可能会延迟,尤其是在处理 $http 请求时。

console.log($scope.persons); //last

将立即被调用,因为代码是从上到下执行的,并且承诺 - 再次 - 可能会有一些延迟。

在实际情况下,您将在控制器中定义一个空数组:

.controller('personsCtrl', function($scope, personService) {
     $scope.persons = [];
});

调用服务并等待服务returns数据:

.controller('personsCtrl', function($scope, personService) {
     $scope.persons = [];
     personService.getPersons()
          .then(function(result){
               $scope.persons = result.data;
          });
});

并填充将绑定到 UI 的 $scope.persons 并更新界面。

如果您在填充 $scope.persons 之前需要做一些其他事情,您可以使用另一个 promise 链接。

如果您想更深入地了解 promises,我建议您阅读这篇文章 article,这是我找到的最好的解释。

如果您有兴趣遵循一些关于控制器、承诺和构建服务方式的非常好的指南John Papa Style Guide