Typescript 使用rxjs运算符在订阅上延迟后输出
我需要获得如下输出:Typescript 使用rxjs运算符在订阅上延迟后输出,typescript,rxjs,operators,delay,Typescript,Rxjs,Operators,Delay,我需要获得如下输出: computing 1 5 6 7 8 wait 2 seconds computing 2 5 6 7 8 wait 2 seconds ... 但是使用以下代码 from([1,2,3,4]).pipe( concatMap(n => of(n).pipe( tap(n => {console.log(`computing ${n}`)}), concatMap(n => from([5,6,7,8]))
computing 1
5
6
7
8
wait 2 seconds
computing 2
5
6
7
8
wait 2 seconds
...
但是使用以下代码
from([1,2,3,4]).pipe(
concatMap(n => of(n).pipe(
tap(n => {console.log(`computing ${n}`)}),
concatMap(n => from([5,6,7,8])),
delay(2000)
))
).subscribe((val) => {console.log(val)}, () => {}, () => {console.log(`end`)})
输出将是
computing 1
wait 2 seconds
5
6
7
8
computing 2
wait 2 seconds
5
6
7
8
computing 3
因为延迟将在最里面的展平后生效,并导致下一个计算x字符串在值之后立即打印。相反,我需要在不获得初始延迟的情况下获得上述示例输出,这可能吗?首先,我们设置一个函数,创建一个开放一段时间的可观察对象,然后完成 const nothingFor=ms=>timerms.pipeconcatMapToEMPTY; 然后我们使用它来生成一个新的操作符,它的行为类似于delay*,但在之后应用延迟 const appendDelay=delay=>source$=> 对于Source$,nothingFordelay.pipeconcatal; 然后我们把它放在你最初使用延迟的地方 从[1,2,3,4] 管 concatMapn=> 水管 tapn=>{ log`computing${n}`; }, concatMapn=>from[5,6,7,8]。pipeappendDelay2000
*嗯,有点。延迟延迟相同数量的每次发射。如果这更像延迟,它将在每次发射后而不是在源完成后添加延迟。首先,我们设置一个函数,创建一个开放一段时间的可观察对象,然后完成 const nothingFor=ms=>timerms.pipeconcatMapToEMPTY; 然后我们使用它来生成一个新的操作符,它的行为类似于delay*,但在之后应用延迟 const appendDelay=delay=>source$=> 对于Source$,nothingFordelay.pipeconcatal; 然后我们把它放在你最初使用延迟的地方 从[1,2,3,4] 管 concatMapn=> 水管 tapn=>{ log`computing${n}`; }, concatMapn=>from[5,6,7,8]。pipeappendDelay2000
*嗯,有点。延迟延迟相同数量的每次发射。如果这更像延迟,它将在每次发射后而不是在源完成后增加延迟。这个问题的关键是,我们只想在第一个可观测源的第一次发射后引入延迟 我们可以将concatMap与delayWhen操作符结合使用,让我们选择条件延迟。条件延迟可以建立在第一个可观察到的迭代的索引之上。如果索引为0,则没有延迟,否则有2秒延迟 在第一个可观察和后条件延迟中的每个项目发射之后,我们使用switchMap切换到第二个可观察流,这将帮助我们获得所需的输出
import { from, iif, interval, of } from "rxjs";
import { concatMap, delayWhen, map, switchMap, tap } from "rxjs/operators";
const a$ = from([1, 2, 3, 4]);
const b$ = from([5, 6, 7, 8]);
const conditionalDelay$ = index => y =>
iif(() => index === 0, interval(0), interval(2000));
const logDelay = index => () => {
if (index !== 0) console.log("Wait for 2 seconds");
};
const result$ = a$.pipe(
concatMap((x, index) =>
of(x).pipe(
tap(logDelay(index)),
delayWhen(conditionalDelay$(index))
)
),
switchMap(x => {
console.log("Computing", x);
return b$.pipe(map(y => console.log(y)));
})
);
result$.subscribe(x => console.log(x));
这个问题的关键是,我们只想在第一个可观测源的第一次发射之后引入延迟 我们可以将concatMap与delayWhen操作符结合使用,让我们选择条件延迟。条件延迟可以建立在第一个可观察到的迭代的索引之上。如果索引为0,则没有延迟,否则有2秒延迟 在第一个可观察和后条件延迟中的每个项目发射之后,我们使用switchMap切换到第二个可观察流,这将帮助我们获得所需的输出
import { from, iif, interval, of } from "rxjs";
import { concatMap, delayWhen, map, switchMap, tap } from "rxjs/operators";
const a$ = from([1, 2, 3, 4]);
const b$ = from([5, 6, 7, 8]);
const conditionalDelay$ = index => y =>
iif(() => index === 0, interval(0), interval(2000));
const logDelay = index => () => {
if (index !== 0) console.log("Wait for 2 seconds");
};
const result$ = a$.pipe(
concatMap((x, index) =>
of(x).pipe(
tap(logDelay(index)),
delayWhen(conditionalDelay$(index))
)
),
switchMap(x => {
console.log("Computing", x);
return b$.pipe(map(y => console.log(y)));
})
);
result$.subscribe(x => console.log(x));
对您的代码进行一个小小的调整,就可以让它按照您想要的方式工作。与简单地返回concatMap中的所需可观测值不同,您可以返回一个可观测值,第一个可观测值发出所需可观测值,然后是一个不发出任何信息的可观测值,然后在延迟后完成 为此,我们可以使用和: 来自[1,2,3,4]。管道 concatMapn=>concat 水管 tapn=>{console.log`computing${n}`}, concatMapn=>from[5,6,7,8] , NEVER.pipetakunteltimer2000//不发射任何东西,然后在2000毫秒后完成 .subscribebeval=>{console.logval},=>{},=>{console.log`end`}
这是一个有效的演示。对您的代码进行一个小的调整就可以让它按照您想要的方式工作。与简单地返回concatMap中的所需可观测值不同,您可以返回一个可观测值,第一个可观测值发出所需可观测值,然后是一个不发出任何信息的可观测值,然后在延迟后完成 为此,我们可以使用和: 来自[1,2,3,4]。管道 concatMapn=>concat 水管 tapn=>{console.log`computing${n}`}, concatMapn=>from[5,6,7,8] , NEVER.pipetakunteltimer2000//不发射任何东西,然后在2000毫秒后完成 .subscribebeval=>{console.logval},=>{},=>{console.log`end`} 这是一个工作演示