Last active
October 11, 2016 16:44
-
-
Save viktor-shmigol/7772d296aac685cad108cf9fccdd7e32 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Http, RequestOptions, ConnectionBackend, RequestOptionsArgs, Response } from '@angular/http' | |
import { Injectable } from '@angular/core' | |
import { PromiseTrackerService } from './promise_traker' | |
import { Observable } from 'rxjs' | |
import 'rxjs/add/operator/map'; | |
export class HttpLoading extends Http { | |
constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, private promiseTrackerService: PromiseTrackerService ) { | |
super(backend, defaultOptions); | |
} | |
get(url: string, options?: RequestOptionsArgs):Observable<Response> { | |
var Deferred = function() { | |
this.promise = new Promise((function(resolve, reject) { | |
this.resolve = resolve; | |
this.reject = reject; | |
}).bind(this)); | |
this.then = this.promise.then.bind(this.promise); | |
this.catch = this.promise.catch.bind(this.promise); | |
}; | |
var d = new Deferred(); | |
this.promiseTrackerService.reset({ | |
promiseList: [d.promise], | |
delay: 1300, // Show loader if the response is taking longer than 1300 sec | |
minDuration: 1300 | |
}); | |
return super.get(url, options).map( | |
(resp) => { | |
d.resolve(); | |
return resp; | |
} | |
).catch( | |
error=> { | |
d.resolve(); | |
return Observable.throw(error || 'backend server error'); | |
} | |
) | |
} | |
} | |
in app.ts | |
export class MyApp { | |
constructor(private tracker: PromiseTrackerService) { } | |
and to bootstrap => | |
{ provide: Http, useFactory: (backend: XHRBackend, defaultOptions: RequestOptions, promiseTrackerService: PromiseTrackerService) => new HttpLoading(backend, defaultOptions, promiseTrackerService), | |
deps: [XHRBackend, RequestOptions, PromiseTrackerService] | |
} | |
app.html | |
<div *ngIf="tracker.isActive();" class="search-loader-wrap"> | |
<img class="search-loader" src="build/images/loading.gif"/> | |
</div> | |
promiseTrackerService.ts | |
import { Injectable } from '@angular/core'; | |
import { Subscription } from 'rxjs/Subscription'; | |
@Injectable() | |
export class PromiseTrackerService { | |
promiseList: Array<Promise<any> | Subscription> = []; | |
delayPromise: number | any; | |
durationPromise: number | any; | |
delayJustFinished: boolean = false; | |
minDuration: number; | |
reset(options: IPromiseTrackerOptions) { | |
this.minDuration = options.minDuration; | |
this.promiseList = []; | |
options.promiseList.forEach(promise => { | |
if (!promise || promise['busyFulfilled']) { | |
return; | |
} | |
this.addPromise(promise); | |
}); | |
if (this.promiseList.length === 0) { | |
return; | |
} | |
this.delayJustFinished = false; | |
if (options.delay) { | |
this.delayPromise = setTimeout( | |
() => { | |
this.delayPromise = null; | |
this.delayJustFinished = true; | |
}, | |
options.delay | |
); | |
} | |
if (options.minDuration) { | |
this.durationPromise = setTimeout( | |
() => { | |
this.durationPromise = null; | |
}, | |
options.minDuration + (options.delay || 0) | |
); | |
} | |
} | |
private addPromise(promise: Promise<any> | Subscription) { | |
if (this.promiseList.indexOf(promise) !== -1) { | |
return; | |
} | |
this.promiseList.push(promise); | |
if (promise instanceof Promise) { | |
promise.then.call( | |
promise, | |
() => this.finishPromise(promise), | |
() => this.finishPromise(promise) | |
); | |
} | |
else if (promise instanceof Subscription) { | |
promise.add(() => this.finishPromise(promise)); | |
} | |
} | |
private finishPromise(promise: Promise<any> | Subscription) { | |
promise['busyFulfilled'] = true; | |
const index = this.promiseList.indexOf(promise); | |
if (index === -1) { | |
return; | |
} | |
this.promiseList.splice(index, 1); | |
} | |
isActive() { | |
if (this.delayPromise) { | |
return false; | |
} | |
if (!this.delayJustFinished) { | |
if (this.durationPromise) { | |
return true; | |
} | |
return this.promiseList.length > 0; | |
} | |
this.delayJustFinished = false; | |
if (this.promiseList.length === 0) { | |
this.durationPromise = null; | |
} | |
return this.promiseList.length > 0; | |
} | |
} | |
export interface IPromiseTrackerOptions { | |
minDuration: number; | |
delay: number; | |
promiseList: Promise<any>[]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment