Reputation: 56
The following code should execute multiple long-running HTTP requests sequentially:
Some of the requests can take up to 30 seconds, so the code needs to make sure that second request waits for the first request to finish. In addition, there needs to be one request for every id provided by this.service.getAll()
.
However, I was not able to achieve the desired behavior with following code. Instead, after the completion of the first HTTP request (30 seconds) no further requests were sent. My assumption is that concatMap
somehow does not buffer the other accounts while waiting for the current request to complete.
Component:
this.service.getAll().pipe(
concatAll(), // flatten the observable
concatMap(acc => this.service.update(acc.id, {synchronize: true}).pipe(delay(1000)))
).subscribe(() => {
this.someFlag = false;
});
Service:
getAll(): Observable<Account[]> {
return this.http.get<Account[]>('someUrl');
}
// The request can take up to 30 seconds
update(id: number, account: Account): Observable<Account> {
return this.http.put<Account>('someUrl', account);
}
How can I achieve the desired behavior?
Upvotes: 1
Views: 431
Reputation: 13079
Make sure that your observables completes after emitting once by using take(1)
or first()
.
this.service.getAll().pipe(
concatMap(acc => this.service.update(acc.id, {synchronize: true}).pipe(take(1), delay(1000)))
).subscribe(() => {
this.someFlag = false;
});
You also may want to do some error handling, but that's another case.
Upvotes: 2
Reputation: 3431
Could you use promise serial in this case? Making sure all requests in sequence
// example.js
const Promise_serial = require('promise-serial');
const promises =
Array(15).fill()
.map((_, i) =>
() => new Promise(resolve => {
console.log('promise '+i+' start');
setTimeout(
() => {
console.log('promise '+i+' end');
resolve('output-'+i);
},
500
);
})
);
console.log('### Run promises in sequence')
Promise_serial(promises)
.then(() => {
console.log('### Run promises in series of 5')
return Promise_serial(promises, {parallelize: 5});
})
node example.js prints:
### Run all promises in sequence
promise 0 start
promise 0 end
promise 1 start
promise 1 end
promise 2 start
promise 2 end
promise 3 start
promise 3 end
promise 4 start
promise 4 end
promise 5 start
promise 5 end
promise 6 start
promise 6 end
promise 7 start
promise 7 end
promise 8 start
promise 8 end
promise 9 start
promise 9 end
promise 10 start
promise 10 end
promise 11 start
promise 11 end
promise 12 start
promise 12 end
promise 13 start
promise 13 end
promise 14 start
promise 14 end
Upvotes: 1