RXJS:从其他可观察值触发的可观察值跳过值

时间:2020-04-23 17:40:22

标签: angular rxjs observable

我正在尝试实现以下行为: 我有一个可观察到的源,它每秒发出一次。 如果另一个可观察的(mySubject)发出了值,我试图在一段时间(10秒)内忽略值。 这就是我来的目的:

this.source.pipe(
      takeUntil(this.mySubject),
      repeatWhen((observable) => observable.pipe(delay(10000))),
      tap((x) => console.log(x)),
).subscribe();

现在,每发射mySubject,它就会停止发射源10秒钟。

问题是,如果再次发射mySubject来重置10秒的“计数”,而又忽略10秒而又不发射任何东西,则我需要它。

我该如何实现?

2 个答案:

答案 0 :(得分:4)

恐怕这需要更复杂的解决方案:

CREATE FUNCTION `CantConLetra` ( Numero Decimal(18,2) )
RETURNS VARCHAR(180)
BEGIN
    DECLARE ImpLetra VARCHAR(180);
    DECLARE lnEntero INT;
    DECLARE lcRetorno VARCHAR(512);
    DECLARE lnTerna INT;
    DECLARE lcMiles VARCHAR(512);
    DECLARE lcCadena VARCHAR(512);
    DECLARE lnUnidades INT;
    DECLARE lnDecenas INT;
    DECLARE lnCentenas INT;
    DECLARE lnFraccion INT;
    DECLARE tieneMillones INT;
    DECLARE sFraccion VARCHAR(15);

    SET lnEntero = FLOOR(Numero);
    SET lnFraccion = (Numero - lnEntero) * 100;
    SET lcRetorno = '';
    SET lnTerna = 1;
  WHILE(lnEntero > 0) DO 
            -- Recorro terna por terna
            SELECT lcCadena = '';
            SET lnUnidades = lnEntero % 10;
            SET lnEntero = FLOOR(lnEntero/10);
            SET lnDecenas = lnEntero % 10;
            SET lnEntero = FLOOR(lnEntero/10);
            SET lnCentenas = lnEntero % 10;
            SET lnEntero = FLOOR(lnEntero/10);
            -- Analizo las unidades
            SET lcCadena =
            CASE -- UNIDADES 
                WHEN lnUnidades = 1 AND lnTerna = 1 THEN CONCAT(lcCadena,  'UNO ')
                WHEN lnUnidades = 1 AND lnTerna <> 1 THEN CONCAT(lcCadena,  'UN ')
                WHEN lnUnidades = 2 THEN CONCAT(lcCadena,  'DOS ')
                WHEN lnUnidades = 3 THEN CONCAT(lcCadena,  'TRES ')
                WHEN lnUnidades = 4 THEN CONCAT(lcCadena,  'CUATRO ')
                WHEN lnUnidades = 5 THEN CONCAT(lcCadena,  'CINCO ')
                WHEN lnUnidades = 6 THEN CONCAT(lcCadena,  'SEIS ')
                WHEN lnUnidades = 7 THEN CONCAT(lcCadena,  'SIETE ')
                WHEN lnUnidades = 8 THEN CONCAT(lcCadena,  'OCHO ')
                WHEN lnUnidades = 9 THEN CONCAT(lcCadena,  'NUEVE ')
                ELSE lcCadena
                END; -- UNIDADES 
            -- Analizo las decenas
            SET lcCadena =
            CASE -- DECENAS 
              WHEN lnDecenas = 1 THEN
                CASE lnUnidades
                  WHEN 0 THEN 'DIEZ '
                  WHEN 1 THEN 'ONCE '
                  WHEN 2 THEN 'DOCE '
                  WHEN 3 THEN 'TRECE '
                  WHEN 4 THEN 'CATORCE '
                  WHEN 5 THEN 'QUINCE '
                  WHEN 6 THEN 'DIEZ Y SEIS '
                  WHEN 7 THEN 'DIEZ Y SIETE '
                  WHEN 8 THEN 'DIEZ Y OCHO '
                  WHEN 9 THEN 'DIEZ Y NUEVE '
                END
              WHEN lnDecenas = 2 THEN
              CASE lnUnidades
                WHEN 0 THEN 'VEINTE '
                ELSE CONCAT(lcCadena,  'VEINTI')
              END
              WHEN lnDecenas = 3 THEN
              CASE lnUnidades
                WHEN 0 THEN 'TREINTA '
                ELSE CONCAT(lcCadena,  'TREINTA Y ')
              END
              WHEN lnDecenas = 4 THEN
                CASE lnUnidades
                    WHEN 0 THEN 'CUARENTA'
                    ELSE CONCAT(lcCadena,  'CUARENTA Y ')
                END
              WHEN lnDecenas = 5 THEN
                CASE lnUnidades
                    WHEN 0 THEN 'CINCUENTA '
                    ELSE CONCAT(lcCadena,  'CINCUENTA Y ')
                END
              WHEN lnDecenas = 6 THEN
                CASE lnUnidades
                    WHEN 0 THEN 'SESENTA '
                    ELSE CONCAT(lcCadena,  'SESENTA Y ')
                END
              WHEN lnDecenas = 7 THEN
                 CASE lnUnidades
                    WHEN 0 THEN 'SETENTA '
                    ELSE CONCAT(lcCadena,  'SETENTA Y ')
                 END
              WHEN lnDecenas = 8 THEN
                CASE lnUnidades
                    WHEN 0 THEN 'OCHENTA '
                    ELSE  CONCAT(lcCadena,  'OCHENTA Y ')
                END
              WHEN lnDecenas = 9 THEN
                CASE lnUnidades
                    WHEN 0 THEN 'NOVENTA '
                    ELSE CONCAT(lcCadena,  'NOVENTA Y ')
                END
              ELSE lcCadena
            END; -- DECENAS 
            -- Analizo las centenas
            SET lcCadena =
            CASE -- CENTENAS 
              WHEN lnCentenas = 1 AND lnTerna = 3 THEN CONCAT(lcCadena,  'CIEN ')
              WHEN lnCentenas = 1 AND lnUnidades = 0 AND lnDecenas = 0 THEN CONCAT(lcCadena,  'CIEN ')
              WHEN lnCentenas = 1 AND lnTerna <> 3 THEN CONCAT(lcCadena,  'CIENTO ')
              WHEN lnCentenas = 2 THEN CONCAT(lcCadena,  'DOSCIENTOS ')
              WHEN lnCentenas = 3 THEN CONCAT(lcCadena,  'TRESCIENTOS ')
              WHEN lnCentenas = 4 THEN CONCAT(lcCadena,  'CUATROCIENTOS ')
              WHEN lnCentenas = 5 THEN CONCAT(lcCadena,  'QUINIENTOS ')
              WHEN lnCentenas = 6 THEN CONCAT(lcCadena,  'SEISCIENTOS ')
              WHEN lnCentenas = 7 THEN CONCAT(lcCadena,  'SETECIENTOS ')
              WHEN lnCentenas = 8 THEN CONCAT(lcCadena,  'OCHOCIENTOS ')
              WHEN lnCentenas = 9 THEN CONCAT(lcCadena,  'NOVECIENTOS ')
              ELSE lcCadena
            END; -- CENTENAS 
            -- Analizo la terna
            IF lnTerna = 3 AND (lnUnidades + lnDecenas + lnCentenas <> 0) THEN
                SET tieneMillones = 1;
            END IF;
            SET lcCadena =
            CASE -- TERNA 
                WHEN lnTerna = 1 THEN lcCadena
                WHEN lnTerna = 2 AND (lnUnidades + lnDecenas + lnCentenas <> 0) THEN CONCAT(lcCadena,  'MIL ')
                WHEN lnTerna = 3 AND (lnUnidades + lnDecenas + lnCentenas <> 0) AND lnUnidades = 1 AND lnDecenas = 0 AND lnCentenas = 0 THEN CONCAT(lcCadena, 'MILLON ')
                WHEN lnTerna = 3 AND (lnUnidades + lnDecenas + lnCentenas <> 0) AND NOT (lnUnidades = 1 AND lnDecenas = 0 AND lnCentenas = 0) THEN CONCAT(lcCadena, 'MILLONES ')
                WHEN lnTerna = 4 AND (lnUnidades + lnDecenas + lnCentenas <> 0) AND tieneMillones = 1 THEN CONCAT(lcCadena,  'MIL ')
                WHEN lnTerna = 4 AND (lnUnidades + lnDecenas + lnCentenas <> 0) THEN CONCAT(lcCadena, 'MIL MILLONES ')
                ELSE ''
                END; -- TERNA 
            -- Armo el retorno terna a terna
            SET lcRetorno = lcCadena  + lcRetorno;
            SET lnTerna = lnTerna + 1;
   END WHILE; -- WHILE 
   IF lnTerna = 1 THEN SET lcRetorno = 'CERO'; END IF;

   SET sFraccion = CONCAT('00', LTRIM(CAST(lnFraccion AS CHAR)));
   SET ImpLetra = CONCAT(RTRIM(lcRetorno), ' PESOS ', SUBSTRING(sFraccion,LEN(sFraccion)-1,2), '/100 PESOS');

    SET ImpLetra = REPLACE(ImpLetra,'CIENTO CON','CIEN CON');
    SET ImpLetra = REPLACE(ImpLetra,'VEINTIUN CON','VEINTIUNO CON');
    SET ImpLetra = REPLACE(ImpLetra,' Y UN CON', ' Y UNO CON');

    IF (LEFT(ImpLetra,2) = 'UN' AND ImpLetra LIKE '%MILLONES%') THEN
        SET ImpLetra = REPLACE(ImpLetra,'MILLONES','MILLON');
    END IF;

   RETURN ImpLetra;
END

答案 1 :(得分:0)

这有点棘手,但这不是(可能)最简单的解决方案,但是您可以按照下面的建议进行操作(也可以查看此Stackblitz demo):

// emits a number starting from 0 in every second
const sourceInterval = interval(1000);

// When semaphore emits, you will wait for two seconds
// The emissions should stop when it emits a true value
// and should resume when it emits a false value (after 
// the minimum waiting interval has passed if it was in
// the middle of one
const semaphore = new Subject<boolean>();

// semaphore will emit in 6 seconds
setTimeout(() => semaphore.next(true), 6000);

sourceInterval
  .pipe(
    // emits an array containing the emission of sourceInterval and semaphore
    withLatestFrom(semaphore.pipe(startWith(false))),

    // exhaustMap maps the value to a inner observable and only accepts new
    //   values when it completes.
    exhaustMap(([sourceIntervalEmission, semaphoreEmission]) =>
      semaphoreEmission
          // this observable completes only after 2 seconds, and release the
          // semaphore before that
        ? new Observable<void>(subscriber => {
            // release the semaphore
            semaphore.next(false);
            // complete the observable after 2 seconds
            setTimeout(() => subscriber.complete(), 2000);
          })
        : of(sourceIntervalEmission) // reemits the sourceInterval value
    )
  ).subscribe(console.log);

// expected output: 0 1 2 3 4 5 * * * 8 9 10...
// on the 6 emission of the sourceInterval, the semaphore emits, so exhaustMap
// gives the control to the `new Observable(...)` that will complete
// only after 2 seconds, releasing the semaphore and the subsequent emissions 
// from the sourceInterval, starting at the 8th emission.