我有两个 http 请求,其中第二个请求(日志请求)应在第一个请求(订单请求)发出值后订阅,并且我执行了一些逻辑,不应被日志请求阻止并且日志请求的结果被忽略。
据我了解,点击是
Used to perform side-effects
https://rxjs.dev/api/operators/tap
并且由于我假设 Log 请求及其响应是 Order 请求的副作用,因此在 Tap 内订阅是一种不好的做法吗?有没有更灵活和 RxJS 的方法来处理这个问题?
const order = of('2- created order').pipe(
delay(100),
tap(console.log)
);
const log = of('4- logged info to log server').pipe(
delay(500),
tap(console.log)
);
console.log('1- started creating order');
order
.pipe(tap(() => log.subscribe()))
.subscribe(() => console.log("3- didn't wait for log server"));
最佳答案
是的,这绝对是不好的做法。
你是对的,tap
存在副作用,但这些副作用不应该涉及其他流,它们应该是简单的副作用,例如分配变量或控制台日志记录等。
问题是,您通常不希望在 pipe
内部的 subscribe
内进行订阅,因为这样做会导致代码非常不可预测且难以维护。
例如,选项卡
内的订阅
看起来足够无害,但想象一下,如果您正在监听连续的数据流,您会有多少个订阅?您愿意跟踪它们全部取消订阅吗?这会不会变得很难理解/调试等等......
您的代码的问题在于,您在某种程度上以命令式方式思考(例如“执行此操作,然后执行此操作,然后...”),而不是从流的 Angular 进行思考。
所以基本上在我看来,而不是思考“在那之前我该怎么做?”您应该考虑如何处理流以及可以对其执行的操作的顺序。
就您而言,是否有任何原因希望在订阅内而不是在管道
中打印第三条消息?
为什么不直接执行以下操作?
order
.pipe(
tap(() => console.log("3- didn't wait for log server")),
switchMap(() => log)
)
.subscribe();
(就像这里:https://stackblitz.com/edit/rxjs-aace8i?file=index.ts)
如果可以的话,我想分析一下你的问题......
开始于
I am having two http requests where the second one (Log request) should be subscribed after the first one (Order request) emits a value
这似乎是一个简单的情况,具有初始可观察值(顺序)并需要使用映射运算符移动到不同的可观察值(日志),我假设您想要丢弃第一个并移动到第二个,所以我选择 switchMap
(或者您可以使用 concatMap
或 mergeMap
)
然后我们就可以:
and I do some logic that should not be blocked by the Log request and the result of log request is ignored.
因为我们已经考虑过如何处理 2 个可观察量,所以如果我们阅读您的句子,它确实表明我们只想在第一个和第二个可观察量之间发生副作用,并且它无论如何都会忽略流的值,所以它显然需要一个简单的点击
对于这么长的消息我感到很抱歉,我希望它听起来不会太迂腐:P
我基本上想说的是,你应该始终查看你的流,并思考如何根据 rxjs 编程风格和你的需要将所有内容组合在一起,而不是某些做事方式是否可以接受,因为这让我真正意识到您已经怀疑这是否不是最佳解决方案。
关于javascript - 在 RxJS Tap 中订阅对于异步逻辑来说是不好的做法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67958700/