【问题标题】:Two different requests return the same results if the requests are made simultaneously如果请求同时发出,则两个不同的请求返回相同的结果
【发布时间】:2021-06-04 14:54:05
【问题描述】:

问题是当我向我的 Spring Boot 后端运行两个不同的 HttpClient 请求时,我得到的两个请求的结果相同(我得到的结果是第一个请求)。大约 30% 的情况会发生这种情况:

//request 1 with url_1= "http://localhost:9099/back/cars/list"
this.http.get(url_1, httpOptions).subscribe(
  data => {
    console.log(data);
  }
);
//request 2  with url_2= "http://localhost:9099/back/goods/list"
this.http.get(url_2, httpOptions).subscribe(
  data => {
    console.log(data);
  }
);

我认为这是一个前端问题的原因是因为当我在后端创建 system.out.println 时,我看到每个请求的响应不同。

只有在两个请求之间休眠 10 毫秒时,我才能得到正确的结果。

找到以下可能有助于分析的代码部分:

1- 父组件

import { Component, OnInit, ViewChild } from '@angular/core';
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
import { NotificationsComponent } from 'app/components/notifications/notifications.component'; 
import { HttpService } from 'app/pages/_services/http.service';
import { CarsListComponent } from '../cars-list/cars-list.component';
import { GoodsListComponent } from '../goods-list/goods-list.component';
@Component({
  selector: 'app-chargement',
  templateUrl: './chargement.component.html',
  styleUrls: ['./chargement.component.css']
})
export class ChargementComponent implements OnInit {
 
  @ViewChild(GoodsListComponent)
  private goodsListComponent!: GoodsListComponent;
  @ViewChild(CarsListComponent)
  private carsListComponent!: CarsListComponent;
  constructor( private route: ActivatedRoute, private httpService:HttpService  ) { }

  ngOnInit(): void {
    this.curContainerId = this.route.snapshot.paramMap.get('id');   
  }
 
    delay = ms => new Promise(res => setTimeout(res, ms));
    async getCustomerInfos(cust){ 
    localStorage.setItem("curCustomerACharger",JSON.stringify(cust)); 
    this.goodsListComponent.actualiser();
    //await this.delay(10);
    this.carsListComponent.actualiser();
  }
 
}

模板:

<div class="main-content" dir="ltr" i18n-dir>
 
    <div class="row">
        <mat-card class="col-md-3" style="padding: 0%;">
     
            <div class="col-md-12" style="padding: 0%;">
        
                <mat-selection-list [multiple]="false" style="background-color: white;">

                    <mat-list-option *ngFor="let cust of contCustomers" style="padding: 0%;"
                        (click)="getCustomerInfos(cust)" [value]="cust.id">
                        <div mat-line style="font-size: 12px;">
                             {{cust.name}} 
                        </div>
                      

                        <mat-divider></mat-divider>
                    </mat-list-option>
                </mat-selection-list>
            </div>
        </mat-card>
        <div class="col-md-9" >
            
            <mat-tab-group>
                <mat-tab>
                    <ng-template mat-tab-label>
                        <mat-icon><i class="nc-icon nc-app"></i></mat-icon>
                        Goods
                    </ng-template>
                    <app-goods-list>
                    </app-goods-list>
                </mat-tab>

                <mat-tab>
                    <ng-template mat-tab-label>
                        <mat-icon>directions_car</mat-icon>
                        Cars
                    </ng-template>
                    <app-cars-list></app-cars-list>
                </mat-tab>

            </mat-tab-group>
        </div>
    </div>
</div>

2- 应用 Http 服务:


import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Router } from '@angular/router';

const httpOptions = {
  headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};

@Injectable({
  providedIn: 'root'
})
export class HttpService {

  constructor(private http: HttpClient,private router: Router) { }

  post(url:string,data:any): Observable<any> {
    return this.http.post(url, data, httpOptions);
  }
  put(url:string,data:any): Observable<any> {
    return this.http.put(url+data.id, data, httpOptions);
  }
  delete(url:string ): Observable<any> {
    return this.http.delete(url ,  httpOptions);
  }
  get(url:string ): Observable<any> {
    return this.http.get(url, httpOptions);
  }
}

3- 应用程序 HttpInterceptor :


import {HttpErrorResponse, HTTP_INTERCEPTORS} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {HttpInterceptor, HttpHandler, HttpRequest} from '@angular/common/http';

import {TokenStorageService} from '../_services/token-storage.service';
import {throwError} from 'rxjs';
import {catchError} from 'rxjs/operators';
import {NotificationsComponent} from 'app/components/notifications/notifications.component';
import {MatDialog} from '@angular/material/dialog';
import {TechDialogElements} from '../common/dialog/TechDialogElements';
import { AuthService } from '../core/auth.service';
 
const TOKEN_HEADER_KEY = 'Authorization';    

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
    constructor(private token: TokenStorageService,
         private notifComponent: NotificationsComponent,
                public dialog: MatDialog,
                private auth:AuthService) {

    }

    intercept(req: HttpRequest<any>, next: HttpHandler) {

        let authReq = req;
        let curUrl = req.url;
        const token = this.token.getToken();
        console.log('in interceptor');
        if (curUrl.startsWith('/bck')) { 
            authReq = req.clone({
                url: 'http://localhost:9099' + req.url,
                headers: req.headers.set(TOKEN_HEADER_KEY, token)
            });
        }
        return next.handle(authReq).pipe(
            catchError((error: HttpErrorResponse) => {
            });
        );
    }

}

export const authInterceptorProviders = [
    {provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true}
];

【问题讨论】:

  • 能否请您提供您的组件的完整代码,并检查网络选项卡,查看从服务器端获取的数据对于这两个请求是否正确
  • 刚刚在帖子中添加了相关部分的代码,谢谢

标签: angular httpclient


【解决方案1】:

所有 HttpClient 方法都返回一个 RxJS Observable 的东西。 HTTP 是一个request/response 协议。您发出请求,它会返回一个响应。 一般来说,一个 observable 可以随着时间的推移返回多个值。来自 HttpClient 的 observable 总是发出单个值然后完成,不再发出。 [Angular 文档 Http][1]

在下一个示例中,我们将使用一个名为 forkJoin 的运算符。如果您熟悉Promises,这与Promise.all() 非常相似。 尝试,为了使我们的请求并行,我们将使用forkJoin;

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, forkJoin } from 'rxjs';

@Component({
  selector: 'app-root',
  templateUrl: 'app/app.component.html'
})
export class AppComponent {
  loadedCharacter: {};
  constructor(private http: HttpClient) {}

  ngOnInit() {
    let books = this.http.get("http://localhost:9099/back/books/list");
    let authors = this.http.get("http://localhost:9099/back/authors/list");

    forkJoin([books, authors]).subscribe(results => {
console.log("results ; ")
    });
  }
}

【讨论】:

  • 为了发出请求,我注入了上面的 HttpService 并在我的组件中使用它的 get() 函数,所以我不会像你那样编写它们。当我像这样使用 forkJoin 时:结果是一样的:``` async getListData(curListConfig: ListDto) { this.queryOnProgress = true; forkJoin([ this.httpService.post(this.url + '/list', curListConfig)]).subscribe( ([data]) => { this.dataSource = new MatTableDataSource(data.items); this.length = data .size; this.queryOnProgress = false; } ); } ```
猜你喜欢
  • 1970-01-01
  • 2018-04-10
  • 1970-01-01
  • 1970-01-01
  • 2022-01-10
  • 1970-01-01
  • 1970-01-01
  • 2019-05-07
  • 1970-01-01
相关资源
最近更新 更多