У меня есть auth.service.ts с переменной HttpClient, загруженной из конструктора с методом вызова моего API, чтобы получить информацию о пользователе и его привилегиях, а также есть ли у него действующий токен. Он работает нормально. Но на некоторых страницах я вызываю api, чтобы получить исходные данные для этой страницы. На этих страницах у меня есть переменная HttpClient, определенная из конструктора. Если я вызываю два запроса почти одновременно, один из ответов каждый раз оказывается пустым.
У меня есть RequestModel класс, в котором я реализовал HTTP-запросы:
export class RequestModel {
private errors: string[];
private responseData: any;
private requestData: any;
private loading: any;
private url: string;
private type: RequestType;
constructor(private authService: AuthService, private http: HttpClient, private loadingController: LoadingController) {}
async request(callback: () => void) {
await this.presentLoading();
this.prepareDataRequest()
.pipe(
finalize(async () => {
await this.loading.dismiss();
})
)
.subscribe(
data => {
this.responseData = data;
if(this.responseData && this.responseData.token) this.authService.setToken(this.responseData.token);
console.log(this.responseData);
callback();
},
err => {
this.errors = ["An error occurred, the data could not be retrieved: Status: " + err.status + ", Message: " + err.statusText];
}
);
}
async presentLoading() {
this.loading = await this.loadingController.create({
message: 'Loading...'
});
await this.loading.present();
}
private prepareDataRequest(): Observable<object> {
var dataUrl = environment.apiEndpoint + this.url;
const config = { headers: new HttpHeaders({'Content-Type': 'application/json; charset=utf-8', 'Authorization': 'Bearer ' + this.authService.getToken()}) };
if (this.type == RequestType.DELETE) return this.http.delete(dataUrl, config);
else if (this.type == RequestType.HEAD) return this.http.head(dataUrl, config);
else if (this.type == RequestType.OPTIONS) return this.http.options(dataUrl, config);
else if (this.type == RequestType.PATCH) return this.http.patch(dataUrl, this.requestData, config);
else if (this.type == RequestType.POST) return this.http.post(dataUrl, this.requestData, config);
else if (this.type == RequestType.PUT) return this.http.put(dataUrl, this.requestData, config);
else if (this.type == RequestType.GET) return this.http.get(dataUrl, config);
else {
this.errors = ["Unsuported request type."];
return;
}
}
}
У меня есть auth.service.ts , где я вызываю api для проверки аутентификации пользователя перед загрузкой страницы.
export class AuthService {
api: RequestModel;
userType = UserType.NULL;
user = null;
userId = null;
private token = null;
constructor(
private storage: Storage,
private platform: Platform,
private helper: JwtHelperService,
private router: Router,
private http: HttpClient,
private loadingController: LoadingController
) {
this.api = new RequestModel(this, http, loadingController);
this.onAuthorizationCheckResponse = this.onAuthorizationCheckResponse.bind(this);
this.authorizationCheck();
this.loadToken();
this.platform.ready().then(() => {
});
}
onAuthorizationCheckResponse() {
var response = this.api.getResponseData();
if(response && response.token) {
this.storage.set(TOKEN_KEY, response.token);
this.token = response.token;
this.userId = response.userId;
if(response.data) {
this.user = response.data;
this.userType = response.data.idUserType;
if(this.userType == UserType.USER || this.userType == UserType.ADMIN) window.dispatchEvent(new CustomEvent('isLoggedIn:true'));
else window.dispatchEvent(new CustomEvent('isLoggedIn:false'));
}
else window.dispatchEvent(new CustomEvent('isLoggedIn:false'));
}
}
loadToken(){
this.storage.get(TOKEN_KEY).then(token => {
if (token) {
//let decoded = this.helper.decodeToken(token);
this.token = token;
}
});
}
getToken(){
if(!this.token) this.loadToken();
return this.token;
}
setToken(token){
if(this.token != token) {
this.token = token;
this.storage.set(TOKEN_KEY, token);
}
}
removeToken(){
this.storage.remove(TOKEN_KEY);
this.token = null;
this.userType = UserType.NULL;
this.user = null;
//this.authorizationCheck();
}
authorization(responseData){
if(responseData.token){
this.setToken(responseData.token);
this.user = responseData.user;
}
}
authentification(responseData){
if(responseData.token){
this.setToken(responseData.token);
}
}
async authorizationCheck(){
this.api.setUrl("login/check");
this.api.setType(RequestType.GET);
await this.api.request(this.onAuthorizationCheckResponse);
}
}
Это пример одной страницы, на которой я вызываю запрос на загрузку данных:
export class QuickMatchPage implements OnInit {
api: RequestModel;
matchModel: MatchModel;
isActive: boolean = false;
isCreator: boolean = false;
constructor(
private authService: AuthService,
private http: HttpClient,
private loadingController: LoadingController,
private alertController: AlertController,
private router: Router
) {
this.api = new RequestModel(authService, http, loadingController);
this.matchModel = new MatchModel();
this.onBeginMatchResponse = this.onBeginMatchResponse.bind(this);
this.matchCheckResponse = this.matchCheckResponse.bind(this);
this.onCreateMatchResponse = this.onCreateMatchResponse.bind(this);
this.onCancelResponse = this.onCancelResponse.bind(this);
}
ngOnInit() {
}
ionViewWillEnter(){
this.matchCheck();
}
async matchCheck(){
this.api.setUrl("match/check");
this.api.setType(RequestType.GET);
await this.api.request(this.matchCheckResponse);
}
async matchCheckResponse(){
if(this.api.getResponseData().success) {
if(this.api.getResponseData().data) {
this.matchModel.fromObject(this.api.getResponseData().data);
this.matchModel.convertToInputAttributes();
this.isActive = true;
if(this.api.getResponseData().data.idMatchState == MatchState.RUNNING) this.router.navigateByUrl("visitor/quick-match/running");
if(this.api.getResponseData().data.idUser == this.authService.userId) this.isCreator = true;
}
}
else {
this.isActive = false;
this.isCreator = false;
const alert = await this.alertController.create({
header: "Alert",
message: this.api.getResponseData().message,
buttons: ["OK"]
});
await alert.present();
}
}
}
После ionWillEnter тех же страниц я вызываю другой HTTP-запрос для получения текущих данных. Пример ответа: Но очень часто второй запрос отправляется до того, как я получу ответ от первого, и поэтому я получаю это из ответа api: I не знаю, что мне делать. Я попытался реализовать Observable, чтобы дождаться изменения значения userId, но когда-нибудь, когда приложение попадает в ionWillEnter, userId уже загружен, и я больше не буду его менять. Я думаю, что целые логи c делать это неправильно. Плохая практика. Несколько советов, как это сделать лучше и один запрос ждет другого? Или какая-то проверка условий, прежде чем я позвоню другому запросу или что-то в этом роде, может быть. Я не знаю.
Конечно, у меня нет этой проблемы, когда пользователь запускает страницу, где мне нужно только проверить аутентификацию и ничего более, а затем go на страницу, где мне нужно загрузить некоторые данные из api.