简体   繁体   English

单击按钮后RXJS取消订阅但有机会再次订阅

[英]RXJS way to unsubscribe after button click but with opportunity to subscribe again

import { reduce, filter, map, mapTo } from 'rxjs/operators'
import { from, fromEvent, scan, Subscription } from 'rxjs'

const button1 = document.getElementById("but1")
const button2 = document.getElementById("but2")
const button3 = document.getElementById("but3")



let click1 = fromEvent(button1, 'click')
.subscribe(result => {
    count3.subscribe(x => p3.innerHTML = `Click count: ${x}`)
})


let click2 = fromEvent(button2, 'click')

here i want to unsubscribe subscription (when i click on second button, but with opportunity to subscribe again when i click first button)在这里我想取消订阅(当我点击第二个按钮时,但当我点击第一个按钮时有机会再次订阅)

I've tried with something like this我试过这样的事情

const sub = click1.subscribe(result => {
        count3.subscribe(x => p3.innerHTML = `Click count: ${x}`)
    })


let click2 = fromEvent(button2, 'click')
    sub.unsubscribe()

But I don't know how to put sub.unsubscribe() into button但我不知道如何将 sub.unsubscribe() 放入按钮

let click3 = fromEvent(button3, 'click')

let three = click3.pipe(mapTo(1))

let c: number = 0

let count3 = three.pipe(scan((acc, val) => acc + val, c))

const d = document.getElementById("d")
const p3 = document.createElement("p")


//count3.subscribe(x => p3.innerHTML = `Click count: ${x}`)

d?.appendChild(p3)

Note: This answer is based on the dialog in the comments of the main question.注意:此答案基于主要问题评论中的对话框。 Taking the question literally this is a worse solution than Narem Murali's从字面上看这个问题比 Narem Murali 的解决方案更糟糕

To do this in a more reactive way you can compose several streams together using only one subscribe.要以一种更具反应性的方式执行此操作,您可以仅使用一个订阅将多个流组合在一起。 This will make manage the subscription simpler and help with nesting, but will involve more stream logic and rxjs operators.这将使管理订阅更简单并有助于嵌套,但将涉及更多流逻辑和 rxjs 运算符。

import { map, fromEvent } from 'rxjs';
import { filter, mergeWith, withLatestFrom } from 'rxjs/operators';

// Get the buttons
const startBtn = document.getElementById('start');
const stopBtn = document.getElementById('stop');
const countBtn = document.getElementById('count');

// Setup base input streams (could be done later separated here for clarity)
const start$ = fromEvent(startBtn, 'click').pipe(map(() => true));
const stop$ = fromEvent(stopBtn, 'click').pipe(map(() => false));

// Merge base input streams so that you only get one output
const shouldTake$ = start$.pipe(mergeWith(stop$));

const count$ = fromEvent(countBtn, 'click').pipe(
  // listen for the count click
  withLatestFrom(shouldTake$), // determine what the latest value from the merged stream
  map(([_, shouldTake]) => shouldTake), // ignore the actual click event and just use shouldTake
  filter((shouldTake) => shouldTake) // Stop the emission if you shouldn't take it
);

// Get the counter span
const counterSpan = document.getElementById('current-count');

let count = 0;

// Actually subscribe to count and do what you care about when you care
count$.subscribe(() => {
  count++;
  counterSpan.innerText = count.toString(10);
});

To see this at work check out this stackblitz https://stackblitz.com/edit/rxjs-zcbaxz?file=index.ts要在工作中查看此内容,查看此 stackblitz https://stackblitz.com/edit/rxjs-zcbaxz?file=index.ts

We can unsubscribe the subscription on the second button click and then when the first button is clicked again, we need clear any subscribes already present, then we reinitialize the subscribtion, finally we subcribe again.我们可以在第二次点击按钮时取消订阅,然后当再次点击第一个按钮时,我们需要清除任何已经存在的订阅,然后我们重新初始化订阅,最后我们再次订阅。

Please let me know if you find this confusion, I will clarify your doubts.如果您发现这种困惑,请告诉我,我会澄清您的疑虑。

Am not sure what you are trying to achieve, but please use the below example and modify it to your use case.不确定您要实现的目标,但请使用以下示例并将其修改为您的用例。

import { mapTo } from 'rxjs/operators';
import { fromEvent, scan, Subscription } from 'rxjs';

const button1 = document.getElementById('but1');
const button2 = document.getElementById('but2');
const button3 = document.getElementById('but3');
let clickCountSubscription = new Subscription();
let interimValue = 0;
const getCount3 = () => {
  let click3 = fromEvent(button3, 'click');
  let three = click3.pipe(mapTo(1));
  return three.pipe(
    scan((acc, val) => {
      interimValue = acc + val;
      return acc + val;
    }, interimValue)
  );
};
let click1 = fromEvent(button1, 'click').subscribe((result) => {
  clickCountSubscription.unsubscribe();
  clickCountSubscription = new Subscription();
  clickCountSubscription.add(
    getCount3().subscribe((x) => (p3.innerHTML = `Click count: ${x}`))
  );
});

let click2 = fromEvent(button2, 'click').subscribe(() => {
  clickCountSubscription.unsubscribe();
});
const d = document.getElementById('d');
const p3 = document.createElement('p');

d?.appendChild(p3);

stackblitz

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM