我正在尝试实现以下行为:
我有一个可观察到的源,它每秒发出一次。
如果另一个可观察的(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秒而又不发射任何东西,则我需要它。
我该如何实现?
答案 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.