问题
I thought I was smart when I tried to load the first page of data and display it while loading the whole set in the background. I used the following code.
ngOnInit() {
this.service.getStuff(0, 10)
.subscribe(suc => this.subset = suc);
this.service.getStuff()
.subscribe(suc => this.data = suc);
}
Then, I set the breakpoint in my API fetching and releasing the first call and holding up unreleased the second. However, according to the network tab in my browser, both calls are pending until both are completed.
Am I anywhere close to have the pre-load working or is it far, far off?
The actual call is performed the usual HttpClient and a GET, returning an observable.
回答1:
You'd be better off using some RxJS operator for this.
This will fire both GETs. First come first served.
merge(this.service.getStuff(0, 10), this.service.getStuff()).subscribe(data => {
// do stuff with data
});
Below, switchMap will make allStuff$ only fire after initialStuff$ has emitted. This will fire the second GET only after the first one emits.
const intialStuff$ = this.service.getStuff(0, 10).pipe(
share()
);
const allStuff$ = intialStuff$.pipe(
switchMap(() => this.service.getStuff())
);
intialStuff$.subscribe(...);
allStuff$.subscribe(...)
Note that since none of requests would block rendering, you should definitely go with the first method. It will fetch all the data faster.
回答2:
Angular HttpClients get()
should be returning a new Observable each time and wouldn't exhibit the behavior you describe.
This is entirely dependent on the implementation of this.service.getStuff()
. If the implementation looks something like below, it should be returning a new Observable
with each call and make it independent of any other call/subscribe.
doStuff() {
return this.http.get('someUrl');
}
Here's an example of the two observable calls working independent of each other - I put a delay to help demonstrate. When you run this, the first call will complete and will render before the second call.
Component with initialization logic:
ngOnInit(){
this.myService.doSomething('todos/1', 100)
.subscribe(resp => {
this.first = resp;
});
this.myService.doSomething('comments', 1500)
.subscribe(resp => {
this.second = resp;
})
}
Example service:
@Injectable()
export class MyService {
constructor(private http: HttpClient){}
doSomething(route: string, withDelay?: number) {
return this.http.get('https://jsonplaceholder.typicode.com/' + route)
.pipe(delay(withDelay));
}
}
来源:https://stackoverflow.com/questions/60121269/how-to-preload-a-portion-of-data-in-angular-while-loading-the-rest