I have this async method inside an Angular service:
public async getListings() {
// generate path, body, headers
return await this.http.post<any>(path, body, headers)
.pipe(
catchError(this.handleError)
).toPromise()
}
I have this setup in an Angular component:
ngOnInit(): void {
this.loadThree();
var self = this;
setInterval(function () {
if ((self.container.scrollHeight - (self.scrollWindow.scrollTop self.scrollWindow.clientHeight) < 1000) {
if (!self.loading) {
self.loading = true;
self.getPages()
self.loading = false;
}
}
}, 1000)
}
public async loadThree() {
this.loading = true;
for(var i = 0; i < 3; i ) {
await this.getPages()
}
this.loading = false;
}
public async getPages() {
// ....
var postResponse = await this.<servicename>.getListings();
// ...
}
The idea is that I generate 3 pages when the site loads, then register an interval to check if the user has scrolled within 1000px of the bottom of the div. If he has, I make the next API call to pull another page.
If the user does a search for new parameters, I clear the results, but it's possible I have already made a request to load a page for old parameters, and those will then be added to the results from the new parameters when the API returns. I'm looking for a way to check if the request is old, so I can ignore the results in the component.
CodePudding user response:
I'm gonna be brave and code this off the top of my head:
interface IPayload {
path: string,
body: any,
headers: any
}
@Injectable({ providedIn: 'root' })
export class MissionService {
// Observable sources
private missionAnnouncedSource = new Subject<IPayload>();
// Observable streams
missionAnnounced$ = this.missionAnnouncedSource.asObservable().pipe(
// switchMap here will auto abort old requests if the request has not completed by the time a new request is made
// you can see the aborts in network tab devtools
switchMap((payload: IPayload) => {
return this.http.post<any>(payload.path, payload.body, payload.headers).pipe(
catchError(() => of(null))
)
})
);
// call this to make new HTTP request
makeNewRequest(path: string, body: any, headers: any) {
const payload: IPayload = {path, body, headers}
this.missionAnnouncedSource.next(payload)
}
}
Then in your component subscribe as follows:
constructor(private missionService: MissionService) {}
ngOnInit(): void {
this.missionService.missionAnnounced$.subscribe((upToDateStuff: any) => {
if (upToDateStuff != null) {
console.log( upToDateStuff )
} else {
console.log( 'something went wrong' )
}
})
}
CodePudding user response:
I found a solution in adapting how I was doing the call. I stopped returning the promise from the service, and instead return the observable:
public getListings() {
// generate path, body, headers
return this.http.post<any>(path, body, headers)
.pipe(
catchError(this.handleError)
)
}
Then in the component, I subscribe to it:
public serviceSub: Subscription;
public getPages() {
this.serviceSub = this.<serviceName>.getListings()
.subscribe(
data => {
console.log(data)
},
error => {
console.log(error)
}
)
} catch (error) {
console.log("Problem happened")
}
}
That way, when my user runs another search with new params I can forget any request that was made before he searched by, as he hits search, calling unsubscribe:
this.serviceSub.unsubscribe();
Any input is welcome, thanks!