我有一个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套件。
答案 0 :(得分:1)
$http
是一种异步方法,因此您需要使用回调
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;
答案 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>