Angular JS方法 - 一个取决于另一个

时间:2017-02-10 16:40:38

标签: javascript angularjs http-post httprequest

我有一个AngularJS(v1.5)客户端,用于安排医院的手术室。该应用程序在该控制器中有一个控制器和两个功能。这两个函数都是$http POST个请求。

第一个调用的方法(requestAccessToken)传递用户名,密码和grant_type以接收OAuth 2 access token,然后将其分配给范围内的变量。这很好。

第二种方法(scheduleORSuite)进行API调用,传递从第一种方法(requestAccessToken)获得的访问令牌。问题是当method()执行时access token为null。我知道我收到了一个有效的访问令牌,因为当我直接调用方法requestAccessToken时,我得到了一个有效的访问令牌。当我逐步浏览Chrome中的调试器时,看起来使用访问令牌的方法(scheduleORSuite)甚至不会等待获取访问令牌的方法返回。

<script type="text/javascript">
    var scheduleORSuiteApp = angular.module('scheduleORSuiteApp', []);

    scheduleORSuiteApp.controller('ScheduleORSuiteController', function ($scope, $http) {
        var viewModel = this;
        viewModel.accessToken = null;
        viewModel.userName = 'theUserName';
        viewModel.password = 'thePassword';

        // This method requests the access token
        viewModel.requestAccessToken = function () {
            $http({
                method : 'POST',
                url: 'https://api.myserver.net/oauth/token',
                data: 'username=' + viewModel.userName + '&password=' + viewModel.password + '&grant_type=password',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded'
                }
            }).then(_requestAccessTokenSuccess, _requestAccessTokenError);
        };

        // This method contacts the API endpoint the schedule an OR suite
        viewModel.scheduleORSuite = function() {
            viewModel.requestAccessToken();
            if (viewModel.accessToken) {
                return; // viewModel.accessToken is null. Exit the method
            }
            $http({
                method : 'POST',
                url: 'https://api.myserver.net/api/scheduleOrSuite',
                data : angular.toJson(viewModel.form),
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': 'Bearer ' + viewModel.accessToken
                }
            }).then(_scheduleORSuiteSuccess, _scheduleORSuiteError);
        };

        // Called when request for access token is successful
        function _requestAccessTokenSuccess(response) {
            viewModel.tokenDisplay = response.data;
        };

        // Called when request for access token results in error
        function _requestAccessTokenError(response) {
            viewModel.tokenDisplay = 'An error occured: ' + response.status;
        };

        // Called when scheduling of operating suite is successful
        function _scheduleORSuiteSuccess(response) {
            viewModel.accessToken = response.data.access_token;
        };

        // Called when scheduling of operating suite results in error
        function _scheduleORSuiteError(response) {
            viewModel.tokenDisplay = 'An error occured: ' + response.data;
        };
    });
</script>

这是使用控制器的HTML表单。

<form ng-submit="viewModel.scheduleORSuite()" novalidate>
...
...
</form>

有没有办法让第二个方法(scheduleORSuite)等到第一个方法(requestAccessToken)完成?需要访问令牌才能调用API来安排OR套件。

3 个答案:

答案 0 :(得分:1)

$http是一种异步方法,因此您需要使用回调

&#13;
&#13;
var scheduleORSuiteApp = angular.module('scheduleORSuiteApp', []);

scheduleORSuiteApp.controller('ScheduleORSuiteController', function($scope, $http) {
  var viewModel = this;
  viewModel.accessToken = null;
  viewModel.userName = 'theUserName';
  viewModel.password = 'thePassword';

  viewModel.requestAccessToken = function() {
    viewModel._requestAccessToken().then(_requestAccessTokenSuccess, _requestAccessTokenError);
  };

  viewModel.scheduleORSuite = function() {
    if (viewModel.accessToken) {
      viewModel._scheduleORSuite.then(_scheduleORSuiteSuccess, _scheduleORSuiteError);
    } else {
      viewModel._requestAccessToken().then(function(response) {
        viewModel.tokenDisplay = response.data;
        viewModel._scheduleORSuite.then(_scheduleORSuiteSuccess, _scheduleORSuiteError);
      }, _requestAccessTokenError);
    }
  };

  // This method contacts the API endpoint the schedule an OR suite
  viewModel._scheduleORSuite = function() {
    return $http({
      method: 'POST',
      url: 'https://api.myserver.net/api/scheduleOrSuite',
      data: angular.toJson(viewModel.form),
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ' + viewModel.accessToken
      }
    });
  };

  // This method requests the access token
  viewModel._requestAccessToken = function() {
    return $http({
      method: 'POST',
      url: 'https://api.myserver.net/oauth/token',
      data: 'username=' + viewModel.userName + '&password=' + viewModel.password + '&grant_type=password',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
      }
    })
  };

  // Called when request for access token is successful
  function _requestAccessTokenSuccess(response) {
    viewModel.tokenDisplay = response.data;
  };

  // Called when request for access token results in error
  function _requestAccessTokenError(response) {
    viewModel.tokenDisplay = 'An error occured: ' + response.status;
  };

  // Called when scheduling of operating suite is successful
  function _scheduleORSuiteSuccess(response) {
    viewModel.accessToken = response.data.access_token;
  };

  // Called when scheduling of operating suite results in error
  function _scheduleORSuiteError(response) {
    viewModel.tokenDisplay = 'An error occured: ' + response.data;
  };
});
&#13;
&#13;
&#13;

答案 1 :(得分:1)

这是因为你的requestAccessToken()方法包含一个promise,并且JavaScript在继续执行其余代码之前不会等待它完成。

最好的办法是从requestAccessToken()返回承诺,以便在scheduleORSuite()中使用

viewModel.requestAccessToken = function () {
    return $http({
        method : 'POST',
        url: 'https://api.myserver.net/oauth/token',
        data: 'username=' + viewModel.userName + '&password=' + viewModel.password + '&grant_type=password',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        }
    });
};

viewModel.scheduleORSuite = function() {
    viewModel.requestAccessToken().then(function(response) {
        viewModel._requestAccessTokenSuccess(response);

        if (viewModel.accessToken) {
            return; // viewModel.accessToken is null. Exit the method
        }
        $http({
            method : 'POST',
            url: 'https://api.myserver.net/api/scheduleOrSuite',
            data : angular.toJson(viewModel.form),
            headers: {
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + viewModel.accessToken
            }
        }).then(_scheduleORSuiteSuccess, _scheduleORSuiteError);
    }, _requestAccessTokenError);
};

我也注意到,您检查访问令牌的变量viewModel.accesstoken是否正在设置,直到_scheduleORSuiteSuccess()函数?我认为这是一个错误,应该在_requestAccessTokenSuccess()设置?

答案 2 :(得分:0)

你想要的是确保请求首先返回访问令牌,然后发出第二个请求。 Todo,使用承诺。 $q库适用于此。有关我所做的更改,请参阅viewModel.requestAccessToken

<script type="text/javascript">
var scheduleORSuiteApp = angular.module('scheduleORSuiteApp', []);

scheduleORSuiteApp.controller('ScheduleORSuiteController', function($scope, $http, $q) {
  var viewModel = this;
  viewModel.accessToken = null;
  viewModel.userName = 'theUserName';
  viewModel.password = 'thePassword';

  // This method requests the access token
  viewModel.requestAccessToken = function() {
    var defer = $q.defer();

    $http({
      method: 'POST',
      url: 'https://api.myserver.net/oauth/token',
      data: 'username=' + viewModel.userName + '&password=' + viewModel.password + '&grant_type=password',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
      }
    }).then(function(response) {
      viewModel.tokenDisplay = response.data;
      defer.resolve(); //fullfills the promise
    }, function(err) {
      viewModel.tokenDisplay = 'An error occured: ' + response.status;
      defer.reject(); //rejects the promise
    });

    return $q; //returns a promise
  };

  // This method contacts the API endpoint the schedule an OR suite
  viewModel.scheduleORSuite = function() {
    viewModel.requestAccessToken().then(function() {
      //On fullfillment of the promise from requestAccessToken...

      if (viewModel.accessToken) {
        return; // viewModel.accessToken is null. Exit the method
      }
      $http({
        method: 'POST',
        url: 'https://api.myserver.net/api/scheduleOrSuite',
        data: angular.toJson(viewModel.form),
        headers: {
          'Content-Type': 'application/json',
          'Authorization': 'Bearer ' + viewModel.accessToken
        }
      }).then(_scheduleORSuiteSuccess, _scheduleORSuiteError);
    }, function() {
      //Error occured in requestAccessToken();
    })
  };


  // Called when scheduling of operating suite is successful
  function _scheduleORSuiteSuccess(response) {
    viewModel.accessToken = response.data.access_token;
  };

  // Called when scheduling of operating suite results in error
  function _scheduleORSuiteError(response) {
    viewModel.tokenDisplay = 'An error occured: ' + response.data;
  };
});
</script>