Angularjs $http 承诺延迟

Angularjs $http promise defer

我正在 1.4.7.

中使用 $http

我需要将我的控制器与任何 $http 请求分开。所以我创建了一个服务如下:

app.service('MyService', function($http, $q, $rootScope) {

  this.getcustomers = function() {
    var deferred = $q.defer();
    $http({
      method: 'GET',
      url: 'http://call/to/rest/api'
    }).then(function successCallback(response) {
      deferred.resolve(response.data);
    }, function errorCallback(response) {
      deferred.reject(error);
    });
    return deferred.promise;
  };

});

然后在我的控制器中我调用该服务如下:

app.controller('registerationCtrl', ['$scope', '$http', 'MyService', '$location', function($scope, $http, MyService, $location) {
  $scope.custlst = [];

  $scope.getcustomers = function() {

    var x = MyService.getcustomers().then(function(data) {
      $scope.custlst = data;
    }, function(err) {
      alert(err);
    });

  }


}]);

现在,上面的方法不起作用,它给了我一个 ReferenceError 现在定义的错误,并指向服务中的 errorCallback 函数。

问题一:脚本有什么问题? 问题2:使用$q重要吗?请记住,服务器可能会很慢。

谢谢。

实际上您不需要使用 $q 来创建承诺。 $http 已经为你做了,所以你可以简单地做:

app.service('MyService', function($http) {
  this.getcustomers = function() {
    return $http.get({
      method: 'GET',
      url: 'http://call/to/rest/api'
    });
  };
});

然后您可以轻松地将 MyService.getcustomers.then() 链接起来,并像这样处理响应:

MyService.getcustomers.then(
  function(data) {
    //do something with data
  },
  function(error) {
    //do something with error
  }
);

我认为你应该看一看 this post 我想更好地了解 promises 的工作原理和行为方式。

编辑: 将已弃用的调用更新为 $http

嗯,在 AngularJS 文档中:https://docs.angularjs.org/api/ng/service/$http

Deprecation Notice The $http legacy promise methods success and error have been deprecated. Use the standard then method instead. If $httpProvider.useLegacyPromiseExtensions is set to false then these methods will throw $http/legacy error.

您不需要使用 $q 承诺。

当您使用 GET 请求时,您可能会使用快捷方式来执行 GET 请求。例如:$http.get();

所以,您可以尝试这样的操作:

MyService服务:只有你需要$http服务。

app.service("MyService", ["$http", function ($http) {
    this.getcustomers = function () {
        return $http.get("http://call/to/rest/api");
    };
}]);

上面的服务允许您在任何控制器中使用该服务。因此,任何控制器都可以使用相同的数据执行其他操作。

registerationCtrl控制器:您需要$scopeMyServicelocation服务。

    app.controller("registerationCtrl", ["$scope", "MyService", "$location", function ($scope, MyService, location) {
        $scope.custlst = [];

        $scope.getcustomers = function () {
            MyService.getcustomers().then(function (response) {
                $scope.custlst = response.data;
            }, function (err) {
                alert(err);
            });
        };
    }]);
}]);

正如我在评论中提到的,您看到的错误是由于 error 变量未在 errorCallback 函数中声明。

至于$q - 不需要使用它,尽管您实现的方式仍然有效。为了使其更简单并遵循承诺的意图(即它们允许异步代码镜像同步代码的代码组合),最好 return $http(或 $http().then() 的原始承诺]):

this.getcustomers = function() {
  return $http({
      method: 'GET',
      url: 'http://call/to/rest/api'
    })
    // pre-process the HTTP response and return the data
    .then(function(response) {
      return response.data;
    })
    // If needed, create a custom error to hide HTTP details from caller
    // otherwise, don't include .catch - the original error will "bubble up"
    .catch(function(error) {
      return $q.reject({
        msg: "something broke"
      });
    });
};

那么,客户端就可以如你所愿的使用了:

MyService.getcustomers()
  .then(function(data) {
    $scope.customers = data;
  })
  .catch(function(error) {
    console.log(error.msg);
  })