假设我有一系列 Action 。它们是提示、响应(对提示)或效果。它们以不规则的间隔出现,但假设每个间隔有 1 秒的延迟。
在每个 PROMPT
操作上,我想发出该操作和一个 BEGIN 操作(假设我们想向用户显示消息 N 秒)。所有其他项目都应延迟 N 秒,之后触发 END 操作(隐藏消息)并且一切继续。
这是我的代码(https://rxviz.com/):
const { interval, from, zip, timer } = Rx;
const { concatMap, delayWhen } = RxOperators;
const PROMPT = 'P';
const RESPONSE = 'R';
const EFFECT = 'E';
const BEGIN = '^';
const END = '&';
const convertAction = action => (action === PROMPT) ? [PROMPT, BEGIN, END] : [action];
// Just actions coming at regular intervals
const action$ = zip(
from([PROMPT, RESPONSE, EFFECT, PROMPT, RESPONSE, EFFECT, EFFECT, EFFECT]),
interval(1000),
(a, b) => a,
);
action$.pipe(
concatMap(action =>
from(convertAction(action)).pipe(
delayWhen(action => (action == END) ? timer(5000) : timer(0)),
),
),
);
我真正想做的是让 PROMPT
之后的第一个 RESPONSE
操作不受延迟的影响。如果它出现在 END Action 之前,它应该立即显示。所以,而不是
P^ &REP^ &REEE
我要收
P^ R &EP^R &EEE
如何在将每个 RESPONSE
放在相应的 PROMPT
之后实现它?假设 PROMPT
和 RESPONSE
之间不会发生任何事件。
最佳答案
如果我理解正确的话,这是一个非常有趣的问题,可以用 Observables 流来解决。这就是我攻击它的方式。
首先,我会将原始逻辑的结果存储在常量 actionDelayed$
中,即我们在每个 PROMPT
之后引入的流,BEGIN
和 END
操作除以延迟。
const actionDelayed$ = action$.pipe(
concatMap(action =>
from(convertAction(action)).pipe(
delayWhen(action => (action == END) ? timer(5000) : timer(0)),
),
),
);
然后我将创建 2 个单独的流,response$
和 promptDelayed$
,在引入延迟之前仅包含 RESPONSE
操作,并且PROMPT
引入延迟后的 Action ,像这样
const response$ = action$.pipe(
filter(a => a == RESPONSE)
)
const promptDelayed$ = actionDelayed$.pipe(
filter(a => a == PROMPT)
)
有了这两个流,我可以创建另一个 RESPONSE
Action 流,紧接在 PROMPT
延迟 Action 发出后发出,就像这样
const responseN1AfterPromptN$ = zip(response$, promptDelayed$).pipe(
map(([r, p]) => r)
)
此时我只需像这样从actionDelayed$
中删除所有RESPONSE
操作
const actionNoResponseDelayed$ = actionDelayed$.pipe(
filter(a => a != RESPONSE)
)
并将 actionNoResponseDelayed$
与 responseN1AfterPromptN$
合并以获得最终流。
完整的代码,用 rxviz 来尝试这是
const { interval, from, zip, timer, merge } = Rx;
const { concatMap, delayWhen, share, filter, map } = RxOperators;
const PROMPT = 'P';
const RESPONSE = 'R';
const EFFECT = 'E';
const BEGIN = '^';
const END = '&';
const convertAction = action => (action === PROMPT) ? [PROMPT, BEGIN, END] : [action];
// Just actions coming at regular intervals
const action$ = zip(
from([PROMPT, RESPONSE, EFFECT, PROMPT, RESPONSE, EFFECT, EFFECT, EFFECT]),
interval(1000),
(a, b) => a,
).pipe(share());
const actionDelayed$ = action$.pipe(
concatMap(action =>
from(convertAction(action)).pipe(
delayWhen(action => (action == END) ? timer(5000) : timer(0)),
),
),
share()
);
const response$ = action$.pipe(
filter(a => a == RESPONSE)
)
const promptDelayed$ = actionDelayed$.pipe(
filter(a => a == PROMPT)
)
const responseN1AfterPromptN$ = zip(response$, promptDelayed$).pipe(
map(([r, p]) => r)
)
const actionNoResponseDelayed$ = actionDelayed$.pipe(
filter(a => a != RESPONSE)
)
merge(actionNoResponseDelayed$, responseN1AfterPromptN$)
在创建 action$
和 actionDelayed$
流时使用 share
运算符可以避免在创建后续流时重复订阅这些流解决方案中使用的流。
关于javascript - 延迟除特定项目外的所有项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64360113/