我有Angular Service,它发出一些http请求,但是我需要从Promise获取这些请求的标头。现在,它是如何工作的,我将我的诺言转换为可观察:
export class SomeService {
constructor(private http: HttpClient, private auth: AuthenticationService) {}
getInfo(id: string): Observable<any> {
return this.auth.getToken().pipe(mergeMap((token: any) => {
let httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
})
}
return this.http.get(`${this.serverURL}/info`, httpOptions);
}))
}
}
getToken() {
return from(this.storage.get(TOKEN_KEY));
}
但是显然我有20-50个请求,并且每个请求都获取auth令牌并不是很好。 我想一次获取令牌并将其用于所有请求。另外,我还有其他来自Promise的标头,需要在我的请求中使用。那么,在这种情况下,如何才能一次获取异步标头(可能在构造函数中)?
答案 0 :(得分:1)
首先考虑是否确实需要优化此代码。性能优化通常仅在经常运行的部分代码中有用。当您说您执行20到50个请求时,听起来好像使用不了很多(应用程序的其他部分可能要占用更多的CPU)。
话虽这么说:如果您仍然想解决这个问题,您确实可以在构造函数中获取令牌。
@extends('person.person-dashboard')
@section('personContent')
<div class="page-body">
<div class="row">
<div class="col-lg-12">
<div class="row-no-margin">
<br>
@if ($message = Session::get('successRemove'))
<div class="alert alert-success alert-block">
<button type="button" class="close" data-dismiss="alert">×</button>
<strong>{{ $message }}</strong>
</div>
@elseif($message = Session::get('failRemove'))
<div class="alert alert-danger alert-block">
<button type="button" class="close" data-dismiss="alert">×</button>
<strong>{{ $message }}</strong>
</div>
@elseif($message = Session::get('defaultRemoveError'))
<div class="alert alert-danger alert-block">
<button type="button" class="close" data-dismiss="alert">×</button>
<strong>{{ $message }}</strong>
</div>
@endif
</div>
<div class="cover-profile">
<div class="profile-bg-img">
<img class="profile-bg-img img-fluid" src="/files/assets/images/bg-img1-30opacity.png"
alt="bg-img">
<div class="card-block user-info">
<div class="col-md-12">
<div class="media-left">
<div class="card-block">
<div class="img-hover">
{{--Check if the picture is null, if so show default image--}}
@if (is_null($person->avatar))
<img class="img-fluid img-radius"
src="{{asset('storage/images/userImage/standard/default.png')}}"
width="150"
height="150" alt="user-img">
<div class="img-overlay img-radius">
<span>
<a href="/person/profile/{{$person->person_id}}/{{$person->last_name}}/uploadfile"
class="btn btn-sm btn-primary">
<i class="icofont icofont-edit"></i></a>
</span>
@else
<img class="img-fluid img-radius"
src="{{asset('storage/images/userImage/standard').'/'.$person->avatar}}"
width="150"
height="150" alt="user-img">
<div class="img-overlay img-radius">
<span>
<a href="/person/profile/{{$person->person_id}}/{{$person->last_name}}/uploadfile"
class="btn btn-sm btn-primary">
<i class="icofont icofont-edit"></i></a>
<a href="/person/profile/{{$person->person_id}}/{{$person->last_name}}/remove"
class="tabledit-delete-button btn btn-sm btn-danger waves-effect waves-light active"
name="delete-image" id="delete-image-button"
onclick="return confirm(trans('collaborators.areYouSure'))">
<i class="icofont icofont-ui-delete"></i></a>
</span>
@endif
</div>
</div>
</div>
</div>
<div class="media-body row">
<div class="col-lg-12">
<div class="user-title">
@if ($person->person_title == null)
<h2>{{$person->first_name}} {{$person->last_name}}</h2>
@else
<h2>{{$person->person_title->name}} {{$person->first_name}} {{$person->last_name}}</h2>
@endif
<span>{{$person->mobile}}, {{$person->email}}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="cover-profile">
<div class="profile-bg-img">
</div>
<div class="card-block user-info">
<div class="col-md-12">
<div class="media-body row">
<div class="col-lg-12">
<div class="user-title">
</div>
</div>
<div>
<div class="pull-right cover-btn">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="tab-header card">
<ul class="nav nav-tabs md-tabs tab-timeline" role="tablist" id="mytab">
<li class="nav-item">
<a class="nav-link active" data-toggle="tab" href="#personal" role="tab"
aria-expanded="true">{{trans('navigation.general')}}</a>
<div class="slide"></div>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#practitioner" role="tab"
aria-expanded="false">{{trans('navigation.practitioner')}}</a>
<div class="slide"></div>
</li>
@isset($practitioner->practitioner_id)
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#availability" role="tab"
aria-expanded="false">{{trans('navigation.availability')}}</a>
<div class="slide"></div>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#absence" role="tab"
aria-expanded="false">{{trans('navigation.absence')}}</a>
<div class="slide"></div>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#contract" role="tab"
aria-expanded="false">{{trans('navigation.contract')}}</a>
<div class="slide"></div>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#training" role="tab"
aria-expanded="false">{{trans('navigation.training')}}</a>
<div class="slide"></div>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#history" role="tab"
aria-expanded="false">{{trans('navigation.history')}}</a>
<div class="slide"></div>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#access" role="tab"
aria-expanded="false">{{trans('navigation.access')}}</a>
<div class="slide"></div>
</li>
@endisset
@empty($practitioner->practitioner_id)
<li class="nav-item">
<a class="nav-link disabled" data-toggle="tab" href="#availability" role="tab"
aria-expanded="false">{{trans('navigation.availability')}}</a>
<div class="slide"></div>
</li>
<li class="nav-item">
<a class="nav-link disabled" data-toggle="tab" href="#absence" role="tab"
aria-expanded="false">{{trans('navigation.absence')}}</a>
<div class="slide"></div>
</li>
<li class="nav-item">
<a class="nav-link disabled" data-toggle="tab" href="#contract" role="tab"
aria-expanded="false">{{trans('navigation.contract')}}</a>
<div class="slide"></div>
</li>
<li class="nav-item">
<a class="nav-link disabled" data-toggle="tab" href="#training" role="tab"
aria-expanded="false">{{trans('navigation.training')}}</a>
<div class="slide"></div>
</li>
<li class="nav-item">
<a class="nav-link disabled" data-toggle="tab" href="#history" role="tab"
aria-expanded="false">{{trans('navigation.history')}}</a>
<div class="slide"></div>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#access" role="tab"
aria-expanded="false">{{trans('navigation.access')}}</a>
<div class="slide"></div>
</li>
@endempty
</ul>
</div>
<div class="tab-content">
<div class="tab-pane active" id="personal" role="tabpanel" aria-expanded="true">
<div class="card">
<div class="card-header">
<button id="edit-btn" type="button"
class="btn btn-editpanel btn-sm btn-primary waves-effect waves-light f-right">
<i class="icofont icofont-edit"></i>
</button>
</div>
<div class="card-block">
@include('person.profile.info-display')
@include('person.profile.info-edit')
</div>
</div>
</div>
<div class="tab-pane" id="practitioner" role="tabpanel" aria-expanded="true">
<div class="card">
@isset($practitioner->practitioner_id)
<div class="card-header">
<button id="edit-practitioner-btn" type="button"
class="btn btn-editpanel btn-sm btn-primary waves-effect waves-light f-right">
<i class="icofont icofont-edit"></i>
</button>
</div>
@endisset
<div class="card-block">
@include('person.profile.practitioner.practitioner-display')
@isset($practitioner->practitioner_id)
@include('person.profile.practitioner.practitioner-edit')
@endisset
</div>
</div>
</div>
<div class="tab-pane" id="availability" role="tabpanel" aria-expanded="false">
<div class="row">
{{trans('navigation.availability')}}
</div>
</div>
<div class="tab-pane" id="contract" role="tabpanel" aria-expanded="false">
<div class="row">
{{trans('navigation.contract')}}
</div>
</div>
<div class="tab-pane" id="training" role="tabpanel" aria-expanded="false">
<div class="row">
@include('person.profile.training.training')
</div>
</div>
<div class="tab-pane" id="absence" role="tabpanel" aria-expanded="false">
<div class="row">
{{trans('navigation.absence')}}
</div>
</div>
<div class="tab-pane" id="history" role="tabpanel" aria-expanded="false">
<div class="row">
{{trans('navigation.history')}}
</div>
</div>
<div class="tab-pane" id="access" role="tabpanel" aria-expanded="false">
<div class="row">
{{trans('navigation.access')}}
</div>
</div>
<!-- tab content end -->
</div>
</div>
</div>
@include("settings.remove-confirmation")
<link rel="stylesheet" type="text/css" href="/files/assets/css/custom-person-profile.css">
<link rel="stylesheet" type="text/css" href="/files/assets/css/custom-j-forms.css">
<script src="/files/js/views/person/person-profile.js"></script>
<script src="/files/js/services/initialization.js"></script>
<script src="/files/js/services/editButton.js"></script>
<script src="/files/js/services/practitioner/editPractitionerButton.js"></script>
<script src="/files/js/services/colors.js"></script>
<script src="/files/js/modules/dataTable.js"></script>
<script src="/files/js/modules/update.js"></script>
<script src="/files/js/modules/create.js"></script>
<script src="/files/js/modules/displayInfo.js"></script>
<script src="/files/js/services/forms.js"></script>
<script src="/files/js/services/validation.js"></script>
<script src="/files/js/settings/setup-ajax-requests.js"></script>
@endsection
之所以可行,是因为您可以多次订阅相同的可观察对象。因此,我们仅对export class SomeService {
// We store the observable here for later use
private getTokenObservable: Observable<string>;
constructor(private http: HttpClient, private auth: AuthenticationService) {
// Retrieve the token now and store the observable
this.getTokenObservable = getToken();
}
getInfo(id: string): Observable<any> {
// Zip the two observables together
return zip(
// Re use the previously stored observable
this.getTokenObservable,
// Also request the last login
this.auth.getLastLogin()
).pipe(mergeMap((result) => {
const token = result[0];
const lastLogin = result[1];
let httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
})
}
return this.http.get(`${this.serverURL}/info`, httpOptions);
}))
}
}
getToken() {
return from(this.storage.get(TOKEN_KEY));
}
的可观察对象进行一次请求并存储一次,然后在每次请求中重新使用它。
还要注意我们如何使用rxjs提供的zip运算符。这使我们可以将两个可观察变量合并在一起,从而可以在一个函数中处理两个可观察变量的结果。
答案 1 :(得分:0)
您可以编写用于获取令牌的单独服务,并且仅调用一次服务。下次需要令牌时,请检查服务变量中是否已具有令牌值,因此可以跳过http请求,只需将令牌返回给请求者即可。
答案 2 :(得分:0)
private _tokenObsevable = new BehaviorSubject<string>(null);
constructor(...) {
this.auth.getToken().subscribe(token => this._tokenObservable.next(token))
}
getInfo(...) {
this._tokenObservable.pipe(
switchMap(token => // rest the same
)
可选,您可以创建类似的吸气剂
get tokenObservable() {
return this._tokenObservable.pipe(filter(val => !!val))
}
在这种情况下,您仅会获得非null值,而且如果令牌不会出现,则会陷入困境
答案 3 :(得分:0)
在这种情况下,您可以在文件中创建实用程序功能,然后将其导入您需要此令牌的任何位置,或者可以创建服务(如果此令牌来自服务器调用),然后可以将其注入所需的所有位置这个令牌。
此令牌也可以保存在const文件中,并在需要的位置导入。