修复在执行http获取请求angularJS时的竞争条件

Fix race condition when doing http get request angularJS

本文关键字:angularJS 竞争 条件 请求 获取 执行 http      更新时间:2023-10-17

我有下面的函数,它检查用户是否输入了正确的密码和用户名。此函数正常工作,但是函数在成功/错误函数被激发之前返回。

因此,函数总是返回true,让函数返回正确值的最佳方法是什么。

angular.module('services.security', [])
    .provider('securityService', function() {

        this.$get = function ($q, $location, $rootScope, $window, $injector) {
             ...
             loginCheck: function(username, password) {
                    var failed = true;                      
                    $injector.get('$http').post(AUTH_URL,
                        {username: username, password: password}, {loginType: "cancel"}
                    ).success(function loginSuccess(data) {
                        failed = false;
                    }).error(function loginFailure(data, status) {
                        failed = true;
                    });
                    return failed;
                },

您可能希望返回promise。所以你可以直接返回你的http呼叫:

return $http("...");

在你的代码中,你可以使用这个返回的承诺来检查它是否成功:

loginCheck(u, p).then(function() {
    //success
}, function() {
    // error
});

您应该对JavaScript Promises进行一些研究。这就是你在这里的工作。问题是HTTP调用(通常)是异步的,这意味着代码不会等到它们完成后再继续。这就是承诺的来源。

函数不应该直接返回true/false值,而应该返回一个表示true/false的promise。然后,您可以将处理程序函数附加到它上,本质上说"只要HTTP调用完成,就将结果传递给这些函数。如果您使用的是Angular的最新版本,例如1.4.4+或1.5.x(不确定Angular 2,但可能仍然适用),$http.post()方法无论如何都会返回promise,所以您可以直接返回。

关键是承诺的.then()方法。这需要两个参数:第一个参数是成功函数,第二个参数是失败函数。所以你应该这样重写你的代码:

loginCheck: function(username, password) {
  var failed = true;                      
  return $injector.get('$http').post(AUTH_URL,
    {username: username, password: password}, {loginType: "cancel"}
  );
}
// ...
// somwhere else where securityService.loginCheck() is used
securityService.loginCheck(username, password).then(
  // success
  function(data) {
    // handle successful login
  },
  // failure
  function(data, status) {
    // handle failed login
  }
);

现在异步代码就是这样写的。阅读Promises和异步概念,这在现代网络开发中非常重要。

  • 承诺简介
  • 承诺A+标准
  • MDN关于最近内置Promise类型的文档
  • $q,Angular的承诺服务