【问题标题】:Angular $scope not available outside my functionAngular $scope 在我的功能之外不可用
【发布时间】:2015-08-19 03:54:10
【问题描述】:

对于 Angular 和 javascript 来说有些新意。我编写了以下控制器,使用工厂服务访问本地 JSON 文件。此代码的大部分源自(或完全采用)this post by Dan Wahlin。我无法访问函数外部的 $scope.books 变量,也无法弄清楚原因。函数内的 console.log 给了我我正在寻找的对象,但外面的对象返回未定义。我在这里做错了什么?谢谢。

app.controller('FormController', ['$scope', 'tocFactory', function ($scope, tocFactory) {

  $scope.books;

  getBooks();

      function getBooks() {
        tocFactory.getBooks().
          success(function(data, status, headers, config) {
            $scope.books = data;
            console.log($scope.books);
          }).
          error(function(data, status, headers, config) {
            // log error
     })
  }
  console.log($scope.books);
  }]);

【问题讨论】:

  • 一切正常,success 内的 console.log 返回正确的对象。欢迎来到异步方法的世界。
  • 我想这取决于你对 OK 的定义。我无法在我的 HTML 中绑定到它,也无法在控制器的其他部分以当前形式使用它。我怎样才能做到这一点?
  • UI 数据绑定的全部意义在于,每当您的数据发生更改时,UI 都会自动反映这一点。您的绑定一定不正确。

标签: javascript ajax angularjs asynchronous angularjs-http


【解决方案1】:

因为您正在制作一个 ajax,然后执行下一行代码。这并不意味着您可以保证在执行下一行代码时您的 ajax 响应已准备就绪。

你总是可以在$http的成功函数中获取它的响应值,当ajax调用成功执行时,该函数会被调用。

阅读这里How asynchronous call works?

【讨论】:

    【解决方案2】:

    实际上,这不是范围问题,而是时间问题。 getBooks 函数是异步执行的,因此当您的控制台日志发生时,它很可能不会绑定到任何东西。您可以使用 interval 轻松测试它,看看这是如何发生的:

    app.controller('FormController', ['$scope', 'tocFactory', function($scope, tocFactory) {
      $scope.books;
      getBooks();
      function getBooks() {
        tocFactory.getBooks()
          .success(function(data, status, headers, config) {
            $scope.books = data;
            console.log($scope.books);
          })
          .error(function(data, status, headers, config) {
            // log error
          })
      }
      setInterval(function(){
        console.log($scope.books);
      }, 1000);
    }]);
    

    【讨论】:

    • 如果响应时间超过 1 秒怎么办?
    • 我的快速演示代码建议使用 setInterval,而不是 setTimeout。它只会永远每 1 秒重复一次记录它,所以很可能它会输出一次或多次 undefined,然后在调用 .success 后输出一些值
    • 哈哈,不用担心,我想。你的回答同样很好地解释了这个问题,我赞成它
    • 我也做了你的.. 干杯:)
    【解决方案3】:

    您可以使用 $q 服务来处理带有 Promise 的异步代码:

    app.controller('FormController', ['$scope', '$q', 'tocFactory', function ($scope,  $q, tocFactory)
    {
    
        var getBooks = function()
        {
            var deferred = $q.defer();
    
            tocFactory.getBooks().
            success( function(data, status, headers, config)
            {
                $scope.books = data;
                deferred.resolve();
            } ).
            error( function(data, status, headers, config)
            {
                deferred.reject();
            } );
    
            return deferred.promise;
        };
    
        getBooks().then( function(res)
        {
            console.log($scope.books); // success : your data
        }, function(res)
        {
            console.log($scope.books); // error : undefined
        } );
    
        console.log($scope.books); // undefined
    
    } ] );
    

    我没有测试过这段代码,但它应该可以工作并向您展示承诺原则。 更多关于$q服务:https://docs.angularjs.org/api/ng/service/$q

    【讨论】:

    • 没有必要使用$q,因为$http已经返回了一个promise。甚至更多 - 成功和错误方法现在已弃用 - docs.angularjs.org/api/ng/service/$http - $http 旧承诺方法成功和错误已被弃用。请改用标准 then 方法。如果 $httpProvider.useLegacyPromiseExtensions 设置为 false 那么这些方法将抛出 $http/legacy 错误。
    猜你喜欢
    • 1970-01-01
    • 2016-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-11
    相关资源
    最近更新 更多