Home > Net >  How to send multiple long-running server requests sequentially?
How to send multiple long-running server requests sequentially?

Time:10-25

The following code should execute multiple long-running HTTP requests sequentially:

  1. First HTTP request is started
  2. First HTTP request is finished
  3. Second HTTP request is started
  4. Second HTTP request is finished
  5. Third HTTP request is started
  6. ...

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?

CodePudding user response:

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.

CodePudding user response:

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
  • Related