typescript 每个 http 请求上的 Angular 2 加载器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38144655/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular 2 loader on each http request
提问by ozata
What i am trying to do is:
I want to use the spinner whenever a http request accurs. In other words i want user to see a loading screen whenever a http request happens in my app.component.
My spinner.component and spinner-service files are same with the answer in thisquestion.
And my app.component's component is
我想要做的是:每当出现 http 请求时,我都想使用微调器。换句话说,当我的 app.component 中发生 http 请求时,我希望用户看到加载屏幕。
我的 spinner.component 和 spinner-service 文件与这个问题的答案相同。
而我的 app.component 的组件是
@Component({
selector: 'todoApi',
template: `
<div class="foo">
<spinner-component></spinner-component>
<h1>Internship Project</h1>
<a [routerLink]="['Dashboard']">Dashboard</a>
<a [routerLink]="['Tasks']">List</a>
<router-outlet></router-outlet>
<div>
`,
directives: [ROUTER_DIRECTIVES,SpinnerComponent],
providers: [
ROUTER_PROVIDERS,
]
})
@RouteConfig([
{
path: '/dashboard',
name: 'Dashboard',
component: DashboardComponent,
useAsDefault: true
},{
path: '/tasks',
name: 'Tasks',
component: TaskComponent
},{
path: '/detail/:id',
name: 'TaskDetail',
component: TaskDetailComponent
},
])
To conclue , whenever a http request occurs in one of these routes, i want to show the spinner to user. I know this has been a bad question , but i am new to angular 2 and i would realy be grateful if anyone could help me with that.
Thanks alot!
Edit!:
Solution with Günther's answer:
I wrapped my http
and spinner-service
into a HttpClient
component and used it instead of regular http module. Here is my HttpClient
component:
总而言之,每当在这些路由之一中发生 http 请求时,我都想向用户显示微调器。我知道这是一个不好的问题,但我是 angular 2 的新手,如果有人能帮我解决这个问题,我将不胜感激。
非常感谢!
编辑!:
Günther 回答的解决方案:我将我的http
和包装spinner-service
成一个HttpClient
组件并使用它而不是常规的 http 模块。这是我的HttpClient
组件:
import { Injectable } from '@angular/core';
import { Http, Headers } from '@angular/http';
import { SpinnerService} from './spinner-service';
@Injectable()
export class HttpClient {
constructor(
private http: Http,
public spinner: SpinnerService
){
}
createAuthorizationHeader(headers:Headers) {
headers.append('Authorization', 'Basic ' + btoa('username:password'));
}
get(url) {
this.spinner.start();
let headers = new Headers();
this.createAuthorizationHeader(headers);
return this.http.get(url, { headers: headers }).do(data=> {this.spinner.stop()});
}
post(url, data) {
this.spinner.start();
let headers = new Headers();
this.createAuthorizationHeader(headers);
return this.http.post(url, data, { headers: headers }).do(data=> {this.spinner.stop()});
}
}
采纳答案by Günter Z?chbauer
Use a service that is shared between Http
(there are answers already how about wrapping Http
in your own class) and the <spinner-component>
.
See also https://angular.io/docs/ts/latest/cookbook/component-communication.html
使用在Http
(已经有答案如何包装Http
在您自己的类中)和<spinner-component>
. 另见https://angular.io/docs/ts/latest/cookbook/component-communication.html
In the shared service maintain a counter of started (increase) and completed/failed HTTP requests and notify the <spinner-component>
every time when the counter changes from 0
to >0
or from >0
to 0
to enable or disable itself.
在共享服务维护的开始(增加)和完成/失败的HTTP请求计数器,并通知<spinner-component>
每当从计数器的变化0
来>0
或>0
来0
启用或禁用本身。
回答by Mark Cutajar
Thanks for your answer Günter Z?chbauer's, An example which I built based on my needs. I did not use an HTTP wrapper which would be easier to use, however, this example works with multiple services calls based on your counter suggestion. Hope it helps someone :)
感谢 Günter Z?chbauer 的回答,这是我根据自己的需要构建的示例。我没有使用更易于使用的 HTTP 包装器,但是,根据您的建议,此示例适用于多个服务调用。希望它可以帮助某人:)
Create the Loader service.
import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs/BehaviorSubject'; @Injectable() export class LoaderService { public loaderCounter: BehaviorSubject<number> = new BehaviorSubject<number>(0); displayLoader(value: boolean) { let counter = value ? this.loaderCounter.value + 1 : this.loaderCounter.value - 1; this.loaderCounter.next(counter); } }
Include the service within the providers of your maain module file (Ex: AppModule)
In your main component file (Ex: AppComponent), subscribe to the changes and reflect to the loader (in my case it's a seperate component).
//Imports import { Subscription } from 'rxjs/Subscription'; import { LoaderService } from './core/loader.service'; .. @Component({ selector: 'my-app', template: ` <div class="container-fluid content"> <router-outlet></router-outlet> </div> <spinner [visible]="displayLoader"></spinner> ` }) export class AppComponent implements OnInit, OnDestroy { displayLoader: boolean; loaderSubscription: Subscription; constructor(private loaderService: LoaderService) {} ngOnInit() { this.loaderSubscription = this.loaderService.loaderCounter.subscribe((counter: number) => { this.displayLoader = counter != 0; }); } ngOnDestroy() { this.loaderSubscription.unsubscribe(); } }
Using the loader service:
import { LoaderService } from './core/loader.service'; .. export class SampleComponent implements OnInit { constructor(private _service: SomeService, private loader: LoaderService) { } ngOnInit() { this.loader.displayLoader(true); this._service.getBalance().subscribe( response => ..do something.., () => .. error.., () => this.loader.displayLoader(false) ); } }
创建加载器服务。
import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs/BehaviorSubject'; @Injectable() export class LoaderService { public loaderCounter: BehaviorSubject<number> = new BehaviorSubject<number>(0); displayLoader(value: boolean) { let counter = value ? this.loaderCounter.value + 1 : this.loaderCounter.value - 1; this.loaderCounter.next(counter); } }
在您的主模块文件的提供程序中包含服务(例如:AppModule)
在您的主要组件文件(例如:AppComponent)中,订阅更改并反映到加载器(在我的情况下它是一个单独的组件)。
//Imports import { Subscription } from 'rxjs/Subscription'; import { LoaderService } from './core/loader.service'; .. @Component({ selector: 'my-app', template: ` <div class="container-fluid content"> <router-outlet></router-outlet> </div> <spinner [visible]="displayLoader"></spinner> ` }) export class AppComponent implements OnInit, OnDestroy { displayLoader: boolean; loaderSubscription: Subscription; constructor(private loaderService: LoaderService) {} ngOnInit() { this.loaderSubscription = this.loaderService.loaderCounter.subscribe((counter: number) => { this.displayLoader = counter != 0; }); } ngOnDestroy() { this.loaderSubscription.unsubscribe(); } }
使用加载器服务:
import { LoaderService } from './core/loader.service'; .. export class SampleComponent implements OnInit { constructor(private _service: SomeService, private loader: LoaderService) { } ngOnInit() { this.loader.displayLoader(true); this._service.getBalance().subscribe( response => ..do something.., () => .. error.., () => this.loader.displayLoader(false) ); } }
回答by Gabriel
Just for the people who gets here from now on...
只为以后来到这里的人...
With this solution the spinner will not stop in case of error with the http request. Make sure you do the following:
使用此解决方案,如果 http 请求出错,微调器将不会停止。确保您执行以下操作:
...
return this.http.post(url, data, { headers: headers })
.do(data=> {this.spinner.stop()},
err=> {this.spinner.stop());
...
回答by Jamie Rees
You could also use Pace.js
你也可以使用Pace.js
Would be pretty easy to add
添加会很容易
<head>
<script src="/pace/pace.js"></script>
<link href="/pace/themes/pace-theme-barber-shop.css" rel="stylesheet" />
</head>
You can find the documentation here: http://github.hubspot.com/pace/
您可以在此处找到文档:http: //github.hubspot.com/pace/