web-dev-qa-db-fra.com

Rxjs angular 6/7 mergeMap delay demande http

Je veux envoyer une demande en utilisant ce code (j'ai aussi essayé forkJoin) avec un délai entre les appels:

duplicateElement(id: string): Observable<any> {
    return this.http.get({ routeName: 'route_name', params: { id } });
}

duplicateElements(ids: string[]): Observable<any> {
    return from(ids)
    .pipe(
        mergeMap(id => this.duplicateElement(id).pipe(delay(1000))
    ));
}

mais .pipe (delay (1000) ne fonctionne pas comme prévu: envoie chaque requête http après 1000 mls.

5
JPFs

Maintenant deux alternatives!

Configuration de base

import * as rx from "rxjs";
import * as rxop from "rxjs/operators";

const startTime = new Date();

function getTimestamp() {
  return (new Date().getTime() - startTime.getTime()) / 1000;
}


const desiredDelay = 750;
const serviceDelay = 500;

// simulating service, you can ignore what's inside
var myService = (b: any) => {
  return rx.of(Math.random()).pipe(
    // To simulate long running service
    rxop.delay(serviceDelay),
    // Log the timestap after execution, should be ~ desiredDelay + serviceDelay, so by default 1250ms each emitted value
    rxop.tap(() => console.log(`${b} after service result, ${getTimestamp()}`)),
    // simulating the result
    rxop.map(a => "result" + b)
  );
};

Émettre les valeurs une par une après un délai, exécuter le service et collecter le résultat le plus rapidement possible

of([1, 2, 3, 4, 5])
  .pipe(
    // See the initial values
    tap(console.log),
    // Split array into single values during emit
    // Collect observables and subscribe to next when previous completes
    concatAll(),
    // Emit each value as a sequence of observables with a desired delay
    concatMap(a => of(a).pipe(delay(desiredDelay))),
    // Call service on each value as soon as possible, do not care about the order
    mergeMap(a => myService(a)),
    // Reduce single values back into array
    // Reduces the values from source observable to a single value that's emitted when the source completes
    reduce<any>((acc, val) => [...acc, val], []),
    // See the result, not necessary
    tap(console.log)
  )
  .subscribe();

Appeler le service sur une valeur, attendre un délai, puis appeler le service avec une autre valeur

of([1, 2, 3, 4, 5])
  .pipe(
    // See the initial values
    tap(console.log),
    // Split array into single values during emit
    // Collect observables and subscribe to next when previous completes
    concatAll(),
    // Call the service
    // Map values to inner observable, subscribe and emit in order
    concatMap(a => myService(a).pipe(delay(desiredDelay))),
    // Reduce single values back into array
    // Reduces the values from source observable to a single value that's emitted when the source completes
    reduce<any>((acc, val) => [...acc, val], []),
    // See the result, not necessary
    tap(console.log)
  )
  .subscribe();
2
Jacek Lipiec

Que dis-tu de ça:

duplicateElements(ids: string[]): Observable<any> {
    return interval(1000).pipe( // start emitting every 1000ms
        take(ids.length),  // limit emissions to length of array
        map(i => ids[i]),  // map (change) emission to the array item @ index i 
        mergeMap(id => this.duplicateElement(id)) // add the http request
    )
}
1
dmcgrandle