每个 http 请求上的 Angular 2 加载器
Posted
技术标签:
【中文标题】每个 http 请求上的 Angular 2 加载器【英文标题】:Angular 2 loader on each http request 【发布时间】:2016-11-03 19:42:28 【问题描述】:我想做的是: 每当发生 http 请求时,我都想使用微调器。换句话说,我希望用户在我的 app.component 中发生 http 请求时看到加载屏幕。 我的 spinner.component 和 spinner-service 文件与this 问题中的答案相同。 而我的 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
,
])
总之,每当在这些路由之一中发生 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());
【问题讨论】:
也许您创建自定义服务来执行扩展 Angular 提供的 HttpClass 的 http 请求,并在每次请求时跟踪自定义服务中的isBusy
状态。
【参考方案1】:
使用Http
(已经有答案如何将Http
包装在您自己的类中)和<spinner-component>
之间共享的服务。
另见https://angular.io/docs/ts/latest/cookbook/component-communication.html
在共享服务中维护已启动(增加)和已完成/失败的 HTTP 请求的计数器,并在每次计数器从 0
更改为 >0
或从 >0
更改为 0
时通知 <spinner-component>
启用或禁用自身。
【讨论】:
这对我 Günter 来说是一个非常有用的答案!非常感谢!我会尽我所能,看看包装Http是否能解决问题。 请问你能创建一个例子吗? 对不起,我没有足够的时间。【参考方案2】:感谢您的回答 Günter Zöchbauer,我根据需要构建的示例。我没有使用更易于使用的 HTTP 包装器,但是,根据您的反建议,此示例适用于多个服务调用。希望它可以帮助某人:)
创建加载器服务。
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)
);
【讨论】:
非常酷...但是为什么您的 ajax 调用在组件内部?我认为您应该在进行 ajax 调用的另一个服务中调用加载器服务方法,不是吗? 根据我对 Angular 2 的了解,您有一个服务,您只需在组件级别调用并绑定到您拥有的值。我不太清楚为什么您需要多个服务,因为您仍然需要将响应与组件内的模型/变量绑定。 @MarkCutajar 但问题是在这里我们打算在组件中完全加载加载器,因为它缺乏问题的独创性。 @k11k2 同意,上面的代码并不适用于每个 HttpRequest,这样做,创建 HttpWrapper,并从 HttpWrapper 本身调用加载器服务,正如 MadCatm2 指出的那样。通过发布的代码,它可以更好地控制何时显示它,具体取决于所需的用例。【参考方案3】:只为从现在开始来到这里的人...
使用此解决方案,微调器不会在 http 请求出错的情况下停止。 请确保执行以下操作:
...
return this.http.post(url, data, headers: headers )
.do(data=> this.spinner.stop(),
err=> this.spinner.stop());
...
【讨论】:
【参考方案4】:你也可以使用Pace.js
很容易添加
<head>
<script src="/pace/pace.js"></script>
<link href="/pace/themes/pace-theme-barber-shop.css" rel="stylesheet" />
</head>
您可以在此处找到文档:http://github.hubspot.com/pace/
【讨论】:
以上是关于每个 http 请求上的 Angular 2 加载器的主要内容,如果未能解决你的问题,请参考以下文章
Angular 2 - 如何在等待 http 请求完成时阻止 GUI 渲染
如何在 Angular 2 中发出启用 CORS 的 HTTP 请求?