gpt4 book ai didi

javascript - RxJS 自定义操作符内部变量

转载 作者:塔克拉玛干 更新时间:2023-11-02 22:20:40 24 4
gpt4 key购买 nike

在 RxJS 中使用/改变来自自定义运算符闭包的变量有缺点吗?我意识到它违反了“纯”功能原则,您可以使用 scan 作为这个简单的示例,但我特别询问以下基础模式的具体技术问题:

const custom = () => {

let state = 0;

return pipe(
map(next => state * next),
tap(_ => state += 1),
share()
)
}

// Usage
const obs = interval(1000).pipe(custom())

obs.subscribe()

最佳答案

您在自定义 运算符中存储状态的方式至少存在两个问题。

第一个问题是您这样做意味着运算符不再是引用透明的。也就是说,如果将运算符的调用替换为运算符的返回值,则行为不同:

const { pipe, range } = rxjs;
const { map, share, tap } = rxjs.operators;

const custom = () => {
let state = 0;
return pipe(
map(next => state * next),
tap(_ => state += 1),
share()
);
};

const op = custom();
console.log("first use:");
range(1, 2).pipe(op).subscribe(n => console.log(n));
console.log("second use:");
range(1, 2).pipe(op).subscribe(n => console.log(n));
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://unpkg.com/rxjs@6/bundles/rxjs.umd.min.js"></script>

第二个问题 - 正如另一个答案中提到的 - 不同的订阅将在它们的 next 通知中收到不同的值,因为运算符中的状态是共享的。

例如,如果源 observable 是同步的,连续的订阅将看到不同的值:

const { pipe, range } = rxjs;
const { map, share, tap } = rxjs.operators;

const custom = () => {
let state = 0;
return pipe(
map(next => state * next),
tap(_ => state += 1),
share()
);
};

const source = range(1, 2).pipe(custom());
console.log("first subscription:");
source.subscribe(n => console.log(n));
console.log("second subscription:");
source.subscribe(n => console.log(n));
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://unpkg.com/rxjs@6/bundles/rxjs.umd.min.js"></script>

但是,可以编写一个与您的自定义 运算符非常相似的运算符,并让它在所有情况下都正确运行。为此,有必要确保运算符中的任何状态都是每个订阅

管道运算符只是一个接受可观察值并返回可观察值的函数,因此您可以使用 defer 来确保您的状态是按订阅的,如下所示:

const { defer, pipe, range } = rxjs;
const { map, share, tap } = rxjs.operators;

const custom = () => {
return source => defer(() => {
let state = 0;
return source.pipe(
map(next => state * next),
tap(_ => state += 1)
);
}).pipe(share());
};

const op = custom();
console.log("first use:");
range(1, 2).pipe(op).subscribe(n => console.log(n));
console.log("second use:");
range(1, 2).pipe(op).subscribe(n => console.log(n));

const source = range(1, 2).pipe(op);
console.log("first subscription:");
source.subscribe(n => console.log(n));
console.log("second subscription:");
source.subscribe(n => console.log(n));
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://unpkg.com/rxjs@6/bundles/rxjs.umd.min.js"></script>

关于javascript - RxJS 自定义操作符内部变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52020354/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com