AngularJS没有等待HTTP请求完成

AngularJS not waiting for HTTP request to be done

本文关键字:请求 HTTP 等待 AngularJS      更新时间:2023-09-26

大家好,我这里有以下代码:

angular.module('todomvc')
.factory('todoStorage', function ($http) {
    'use strict';
    var STORAGE_ID = 'todos-angularjs';
    return {
        get: function () {
            $http({method: 'GET', url: '/api/todo.php'}).
            success(function(data, status, headers, config) {
              // this callback will be called asynchronously
              // when the response is available
              return JSON.stringify(data);
            }).
            error(function(data, status, headers, config) {
              // called asynchronously if an error occurs
              // or server returns response with an error status.
            });
        },
        put: function (todos) {
            debugger;
            localStorage.setItem(STORAGE_ID, JSON.stringify(todos));
        }
    };
});

以及

angular.module('todomvc')
.controller('TodoCtrl', function TodoCtrl($scope, $routeParams, $filter, todoStorage, $http) {
    'use strict';
    var todos = $scope.todos = todoStorage.get();
    $scope.newTodo = '';
    $scope.editedTodo = null;
    $scope.$watch('todos', function (newValue, oldValue) {
        $scope.remainingCount = $filter('filter')(todos, { completed: false }).length;
        $scope.completedCount = todos.length - $scope.remainingCount;
        $scope.allChecked = !$scope.remainingCount;
        if (newValue !== oldValue) { // This prevents unneeded calls to the local storage
            todoStorage.put(todos);
        }
    }, true);

我遇到的问题是HTTP请求没有在$scope的代码之前完成$watch正在执行,因此它正在对undefined调用.length。我对Angular来说完全是一个n00b,我想使用这个TodoMVC来让它工作,但我不确定我能做些什么来停止整个过程,而不是将其余的代码包装在http请求的成功回调中。

提前感谢

发布

  • #1您需要从工厂的get方法返回promise,并使用$http.then而不是http的自定义promise方法success
  • #2您需要将其链接起来,以便为scope属性赋值
  • #3当你观察异步分配的属性时,你需要进行null检查,因为当控制器设置好时,观察将运行
  • #4我不确定你是否应该做JSON.stringify响应,因为看起来你需要一个数组数据

在您的工厂

 return {
    get: function () {
      return  $http({method: 'GET', url: '/api/todo.php'}). //Return here
        then(function(response) { //
            return response.data;
        }, function(response) {
          // called asynchronously if an error occurs
          // or server returns response with an error status.
        });
    },

在您的控制器中:-

   var todos;
   todoStorage.get().then(function(data) {
       todos = $scope.todos = data
   });

   $scope.$watch('todos', function (newValue, oldValue) {
       if(!newValue) return;
        $scope.remainingCount = $filter('filter')(todos, { completed: false }).length;
        $scope.completedCount = todos.length - $scope.remainingCount;
        $scope.allChecked = !$scope.remainingCount;
        if (newValue !== oldValue) { // This prevents unneeded calls to the local storage
            todoStorage.put(todos);
        }
    }, true);

使用以下代码:

angular.module('todomvc')
    .factory('todoStorage', function ($http) {
        'use strict';
    var STORAGE_ID = 'todos-angularjs';
    return {
        get: function () {
            return $http({method: 'GET', url: '/api/todo.php'})
        },
        put: function (todos) {
            debugger;
            localStorage.setItem(STORAGE_ID, JSON.stringify(todos));
        }
    };
});

angular.module('todomvc')
.controller('TodoCtrl', function TodoCtrl($scope, $routeParams, $filter, todoStorage, $http) {
    'use strict';
    $scope.newTodo = '';
    $scope.editedTodo = null;
     todoStorage.get()
         .then(function(d){
          $scope.todos=d;
     })
         .catch(function(e){
          console.error(e);
      })
    $scope.$watch('todos', function (newValue, oldValue) {
        $scope.remainingCount = $filter('filter')(todos, { completed: false }).length;
        $scope.completedCount = todos.length - $scope.remainingCount;
        $scope.allChecked = !$scope.remainingCount;
        if (newValue !== oldValue) { // This prevents unneeded calls to the local storage
            todoStorage.put(todos);
        }
    }, true);

$http封装在一个promise中。您可以从服务中返回承诺:

return $http({method: 'GET', url: '/api/todo.php'})

在控制器中,您可以使用then方法指定请求完成时的行为:

 $scope.newTodo = '';
 $scope.editedTodo = null;
todoStorage.get().then(function(result) {
    $scope.todos = result.data;
    $scope.$watch('todos', function (newValue, oldValue) {
        $scope.remainingCount = $filter('filter')($scope.todos, { completed: false }).length;
        $scope.completedCount = todos.length - $scope.remainingCount;
        $scope.allChecked = !$scope.remainingCount;
        if (newValue !== oldValue) { // This prevents unneeded calls to the local storage
            todoStorage.put($scope.todos);
        }
    }, true);
 });

关于如何连锁承诺的一个很好的例子:

http://codepen.io/willh/pen/fCtuw