Reputation: 1147
I have an Angular 5 site that receives data from a REST API, something like 1-4 requests to the API each page, and what happens is that the requests sometimes take a long time(and sometimes not).
Now, all the requests are being performed in one function using Observable :
return this.http.post(url, {headers: this.header})
.map(res => res.json())
.catch(this.handleError)
my question is - could it be that the slow process is happening because an Observable is being used? Would Promises will be better for the performance? Or is there no difference between an Observable and a Promise in performance context?
Upvotes: 6
Views: 6410
Reputation: 7739
The golden rule of performance troubleshooting is this: always measure; never jump to conclusions.
Start by reproducing a scenario where the page is running slowly. Check on the Network tab in your browser's developer console. How long does each network request take? Are the requests running in parallel, or is there a stair-step formation, where each request is not initiated until the previous one completes? Is there a long pause between requests, or does each one start immediately when the previous one finishes? Does the page appear loaded immediately when the last request is finished?
If you're unable to reproduce the problem, consider using a monitoring tool, like sentry.io, to help gather data. Analyze the data and find out what's taking so long. Is there a particular example of a record in your app that triggers this condition?
You should also look at application logs on the server side. How long is the server taking to respond to each request?
If you need to find out in detail what your rxjs code is doing, consider using this tool: https://github.com/cartant/rxjs-spy
I found this very helpful for local development.
Note that rxjs-spy introduces a large performance overhead, and is NOT suitable for production use.
Upvotes: 0
Reputation: 2982
It's not actually fair example by the last comment. More right usage RxJS in this scheme would be in this modified example:
https://stackblitz.com/edit/typescript-uajatd
Working browser performance: https://typescript-uajatd.stackblitz.io
And we can see RxJS mostly wins the race :)
Upvotes: 1
Reputation: 865
According to my tests, a Promise is more performant than an Observable.
I think Yanis-git test is a good start, but only shows part of the picture. It only calculates the starting of the Promise or Observable, but doesn't count the time for its resolution.
Here is the code I modified to take into account the resolution of the async functions as well: https://stackblitz.com/edit/typescript-xhhseh?file=index.ts
import { of, Observable, zip } from 'rxjs';
console.clear();
function testPromise(){
console.time('promise');
const promiseAry = [];
for(let i = 0; i < 10000; i++) {
promiseAry[i] = new Promise((resolve) => {
setTimeout(() => resolve({
name: 'promise'
}))
}).then(user => {
// do something. Prefer not console.log because is ressource consuming.
});
}
Promise.all(promiseAry).then(() =>{
console.timeEnd('promise');
// test Observables after Promises have completed
testObservable();
})
}
function testObservable(){
console.time('observable');
const observeAry = [];
for(let i = 0; i < 10000; i++) {
observeAry[i] = Observable.create((o) => {
setTimeout(() => {
o.next({
name: 'observable'
});
});
});
observeAry[i].subscribe(user => {
// do something. Prefer not console.log because is ressource consuming.
});
}
let source$ = zip(...observeAry);
source$.subscribe(([weatherInfo, tweetInfo]) =>
console.timeEnd('observable')
);
}
testPromise();
When I run the test in Chrome (on Mac), by visiting this page directly and opening the console: https://typescript-xhhseh.stackblitz.io/ I get these results:
promise: 279.65185546875ms
observable: 552.891845703125ms
And a very similar result in Firefox:
promise: 232ms - timer ended
observable: 319ms - timer ended
Running them repeatedly, I always come up with Observable taking more time than Promise, which makes sense especially because Promises are now native to JavaScript, whereas Observables are not, so they wouldn't seem to be as performant.
Special thanks to Yanis-git for coming up with the original test that I forked.
Upvotes: 5
Reputation: 7875
because you question intrigue me. i have create same testing which look like this :
console.time('observable');
for(let i = 0; i < 10000; i++) {
let user$ = of({
name: 'yanis-git'
});
user$.subscribe(user => {
// do something. Prefer not console.log because is ressource consuming.
});
}
console.timeEnd('observable');
console.time('promise');
for(let i = 0; i < 10000; i++) {
new Promise((resolve) => {
resolve({
name: 'promise'
});
}).then(user => {
// do something. Prefer not console.log because is ressource consuming.
});
}
console.timeEnd('promise');
and result looks like this (can be different on your browser / setup but proportion should be the same :
observable: 34.060791015625ms
promise: 103.4609375ms
Another implementation with both async traitment inside :
console.time('observable');
for(let i = 0; i < 10000; i++) {
let user$ = Observable.create((o) => {
setTimeout(() => {
o.next({
name: 'observable'
});
});
});
user$.subscribe(user => {
// do something. Prefer not console.log because is ressource consuming.
});
}
console.timeEnd('observable');
console.time('promise');
for(let i = 0; i < 10000; i++) {
new Promise((resolve) => {
setTimeout(() => resolve({
name: 'promise'
}))
}).then(user => {
// do something. Prefer not console.log because is ressource consuming.
});
}
console.timeEnd('promise');
Result are close but race are win by observable.
observable: 160.162353515625ms
promise: 213.40625ms
if you want to check on stackblitz, please use real browser console to see timer output
Upvotes: 5