Im new to Angular2 e mi chiedevo se c'è un modo per mostrare un indicatore di attività per ogni richiesta HTTP e nascondere le viste fino al completamento?Angular2: mostra l'indicatore di attività per ogni richiesta HTTP e nasconde le visualizzazioni fino al completamento
risposta
Sì, è necessario gestire che per ogni Vista:
- si può avere un servizio per la richiesta HTTP che restituirà un osservabile
- nel componente si avrà uno stato di caricamento
- È necessario impostare lo stato di caricamento su true prima di richiedere i dati dal server , quindi impostarlo su false quando viene eseguito il recupero dei dati.
- Nel modello utilizzare il ngIf per nascondere/mostrare carico o il contenuto
Es:
Il Servizio:
@Injectable()
export class DataService {
constructor(private http: Http) { }
getData() {
return this.http.get('http://jsonplaceholder.typicode.com/posts/2');
}
}
Il Componente:
@Component({
selector: 'my-app',
template : `
<div *ngIf="loading == true" class="loader">Loading..</div>
<div *ngIf="loading == false">Content.... a lot of content <br> more content</div>`
})
export class App {
loading: boolean;
constructor(private dataService: DataService) { }
ngOnInit() {
// Start loading Data from the Server
this.loading = true;
this.dataService.getData().delay(1500).subscribe(
requestData => {
// Data loading is Done
this.loading = false;
console.log('AppComponent', requestData);
}
}
}
Un esempio di lavoro può essere trovato qui: http://plnkr.co/edit/HDEDDLOeiHEDd7VQaev5?p=preview
Un modo è quello di scrivere un intercettore per Angular2 Http. Creando la tua istanza http puoi scambiarla quando stai facendo il bootstrap dell'applicazione usando il metodo "fornire". Una volta fatto questo, è possibile creare un servizio PubSub per pubblicare e sottoscrivere questi eventi dall'intercettore Http ed emettere eventi prima e dopo ogni richiesta effettuata.
Un esempio dal vivo può essere visto su Plunker
Interceptor:
import {Injectable} from 'angular2/core';
import {HTTP_PROVIDERS, Http, Request, RequestOptionsArgs, Response, XHRBackend, RequestOptions, ConnectionBackend, Headers} from 'angular2/http';
import 'rxjs/Rx';
import {PubSubService} from './pubsubService';
@Injectable()
export class CustomHttp extends Http {
_pubsub: PubSubService
constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, pubsub: PubSubService) {
super(backend, defaultOptions);
this._pubsub = pubsub;
}
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.request(url, options));
}
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.get(url,options));
}
post(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.post(url, body, this.getRequestOptionArgs(options)));
}
put(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.put(url, body, this.getRequestOptionArgs(options)));
}
delete(url: string, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.delete(url, options));
}
getRequestOptionArgs(options?: RequestOptionsArgs) : RequestOptionsArgs {
if (options == null) {
options = new RequestOptions();
}
if (options.headers == null) {
options.headers = new Headers();
}
options.headers.append('Content-Type', 'application/json');
return options;
}
intercept(observable: Observable<Response>): Observable<Response> {
this._pubsub.beforeRequest.emit("beforeRequestEvent");
//this will force the call to be made immediately..
observable.subscribe(
null,
null,
() => this._pubsub.afterRequest.emit("afterRequestEvent");
);
return observable
}
}
gli emettitori
import {Subject } from 'rxjs/Subject';
export class RequestEventEmitter extends Subject<String>{
constructor() {
super();
}
emit(value) { super.next(value); }
}
export class ResponseEventEmitter extends Subject<String>{
constructor() {
super();
}
emit(value) { super.next(value); }
}
Il PubSubService
0.123.import {Injectable} from 'angular2/core';
import {RequestEventEmitter, ResponseEventEmitter} from './emitter';
@Injectable()
export class PubSubService{
beforeRequest:RequestEventEmitter;
afterRequest:ResponseEventEmitter;
constructor(){
this.beforeRequest = new RequestEventEmitter();
this.afterRequest = new ResponseEventEmitter();
}
}
bootstrap App
//main entry point
import {bootstrap} from 'angular2/platform/browser';
import {provide} from 'angular2/core';
import {Http, HTTP_PROVIDERS, XHRBackend, RequestOptions} from 'angular2/http';
import {HelloWorldComponent} from './hello_world';
import {CustomHttp} from './customhttp';
import {PubSubService} from './pubsubService'
bootstrap(HelloWorldComponent, [HTTP_PROVIDERS,PubSubService,
provide(Http, {
useFactory: (backend: XHRBackend, defaultOptions: RequestOptions, pubsub: PubSubService)
=> new CustomHttp(backend, defaultOptions, pubsub),
deps: [XHRBackend, RequestOptions, PubSubService]
})
]).catch(err => console.error(err));
Ora nel componente di carico la sua facile come la sottoscrizione agli eventi e impostando una proprietà di mostrare o meno
export class LoaderComponent implements OnInit {
showLoader = false;
_pubsub:PubSubService;
constructor(pubsub: PubSubService) {
this._pubsub = pubsub;
}
ngOnInit() {
this._pubsub.beforeRequest.subscribe(data => this.showLoader = true);
this._pubsub.afterRequest.subscribe(data => this.showLoader = false);
}
}
Anche se questo finisce per essendo un po 'più codice, se stai cercando di essere informato su ogni richiesta nella tua applicazione questo lo farebbe. Una cosa da notare con l'intercettore è che, poiché viene eseguita una sottoscrizione per ogni richiesta, verranno eseguite immediatamente tutte le richieste, che potrebbero non essere quelle necessarie in casi particolari.Una soluzione a ciò è supportare il normale Http di Angular2 e utilizzare CustomHttp come seconda opzione che potrebbe essere iniettata dove necessario. Penserei che nella maggior parte dei casi l'abbonamento immediato funzionasse bene. Mi piacerebbe sentire esempi di quando non lo farebbe.
Penso che tu possa usare .do invece di iscriverti all'intercetta - [Plunker] (http://plnkr.co/edit/OOxfpPP2HUn4Ujy7UrZx?p=preview). 'intercettazione '(osservabile: Osservabile
L'uso di' do() 'dovrebbe essere la risposta corretta in quanto @BrianChance ha suggerito che le richieste vengono fatte due volte quando vi iscrivete a loro poiché sono osservabili freddi. Guarda la scheda di rete durante l'esecuzione del plunk. – Yodacheese
L'implementazione descritta da @ d1820, con 'do()' suggerita da @BrianChance ha funzionato come un fascino se utilizzata in Angular v2.0.1, ma presenta un leggero problema dall'aggiornamento alla v2.2.0. Ceteris paribus, i callback ora vengono chiamati due volte (sia onSuccess che onError). Ho cercato un po 'ma non ho trovato cosa c'è che non va; Inoltre non sono riuscito a trovare una CDN 2.2.0 per creare un plunkr, ma dovrebbe essere facile da riprodurre su un progetto locale. Qualcuno ha idea di cosa potrebbe essere sbagliato? – phl
Aggiungere una classe DAL (livello di accesso ai dati) comune come questo e utilizzare questa classe DAL nei componenti.
Aggiungi indicatore di caricamento come servizio o componente e usa i tuoi stili personalizzati per questo.
export class DAL {
private baseUrl: string = environment.apiBaseUrl;
private getConsolidatedPath(path: string) {
if (path.charAt(0) === '/') {
path = path.substr(1);
}
return `${this.baseUrl}/${path}`;
}
private callStack = [];
private startCall() {
this.loadingIndicator.display(true);
this.callStack.push(1);
}
private endCall() {
this.callStack.pop();
if (this.callStack.length === 0) {
this.loadingIndicator.display(false);
}
}
public get(path: string) {
this.startCall();
return this.http.get(this.getConsolidatedPath(path), { headers: this.getHeaders() })
.map(response => response.json())
.catch(e => this.handleError(e))
.finally(() => this.endCall());
}
public put(path: string, data: any) {
this.startCall();
return this.http.put(this.getConsolidatedPath(path), data, { headers: this.getHeaders() })
.map(response => response.json())
.catch(e => this.handleError(e))
.finally(() => this.endCall());
}
public post(path: string, data: any) {
this.startCall();
return this.http.post(this.getConsolidatedPath(path), data, { headers: this.getHeaders() })
.map(response => response.json())
.catch(e => this.handleError(e))
.finally(() => this.endCall());
}
public delete(path: string, data: any) {
this.startCall();
return this.http.delete(this.getConsolidatedPath(path), { body: data, headers: this.getHeaders() })
.map(response => response.json())
.catch(e => this.handleError(e))
.finally(() => this.endCall());
}
constructor(public http: Http, public loadingIndicator: LoadingIndicatorService) {
}
}
Inoltre @tibbus risposta
Questo è meglio per impostare il tipo di "IsLoading" di numero e tenerlo in servizio.
con booleano:
richiesta 1 inizia -> filatore su -> Richiesta 2 inizia -> richiesta 1 finisce -> trottola off -> Richiesta 2 finisce
con il numero:
richiesta 1 inizia -> filatore su -> richiesta 2 inizia -> richiesta 1 finisce -> richiesta 2 estremità -> filatore off
Servizio
@Injectable()
export class DataService {
constructor(private http: Http) { }
private set fetchCounter(v:number) {
this._fetchCounter = v;
this.isLoadingSource.next(this._fetchCounter > 0)
}
private get fetchCounter() { return this._fetchCounter };
private _fetchCounter:number = 0;
private isLoadingSource = new Subject<boolean>();
public isLoading = this.isLoadingSource.asObservable();
public getData() {
this.fetchCounter++;
return this.http.get('http://jsonplaceholder.typicode.com/posts/2')
.map(r => {
this.fetchCounter--;
return r;
});
}
}
Hai solo bisogno di iscriverti a isLoading da uno qualsiasi dei tuoi componenti.
- 1. Come forzare un programma ad attendere fino al completamento di una richiesta HTTP in JavaScript?
- 2. Node.JS async.parallel non attende fino al completamento di tutte le attività
- 3. Come aspettare fino al completamento di SwingWorker?
- 4. Android - Attività vs Visualizzazioni
- 5. Angular2: HTTP movimentazione
- 6. completamento attività
- 7. Blocco Javascript fino al completamento del precaricamento dell'immagine?
- 8. Caricatore angolare 2 su ogni richiesta http
- 9. richiesta HTTP effettuata più volte in servizio Angular2
- 10. Angular2 modo più semplice per memorizzare le risposte HTTP
- 11. Come posso attendere fino al completamento di Parallel.ForEach
- 12. Intestazioni Angular2/Http (POST)
- 13. Completamento attività iPhone
- 14. Come concatenare le chiamate Http in Angular2
- 15. AutoCompleteTextView nasconde i suggerimenti di completamento automatico
- 16. Come inviare richiesta di richiesta HTTP POST al server
- 17. Migliori pratiche Android - visualizzazioni/attività
- 18. FAB risponde alla tastiera virtuale mostra/nasconde le modifiche
- 19. Chrome Extension: nasconde e mostra l'icona di azione del browser
- 20. Angular2 Http error
- 21. Richiesta Jjery ajax, attendere l'ultima richiesta di completamento
- 22. DataGridview search: mostra solo searchresult e nasconde altre righe?
- 23. Come sapere quando tutte le chiamate HTTP Angular2 sono finite
- 24. CSS: al passaggio del mouse mostra e nasconde diversi div allo stesso tempo?
- 25. La tastiera mostra quindi si nasconde immediatamente quando mostra MFMessageComposeViewController
- 26. Le visualizzazioni "GONE" sono dannose per le prestazioni?
- 27. Ottenere più risorse HTTP contemporaneamente in Angular2
- 28. ng-repeat: mostra un elemento al clic e nasconde gli altri
- 29. C'è un modo per ottenere il layout e le visualizzazioni delle attività correnti tramite adb?
- 30. Angular2 http synchronous
facile e semplice. grande. ty – angryip