RxJS全局var用于不同的流

时间:2018-08-05 18:45:39

标签: javascript rxjs observable

如何为不同的可观察函数创建全局变量?

例如迭代编号,或从数组中删除一个可观察对象,添加另一个对象等的数组。

// RxJS v6+
import { fromEvent, combineLatest } from 'rxjs';
import { mapTo, startWith, scan, tap, map } from 'rxjs/operators';

const setHtml = id => val => (document.getElementById(id).innerHTML = val);

const addOneClick$ = (id, iter) =>
  fromEvent(document.getElementById(id), 'click').pipe(
    mapTo(10),
    startWith(0),
    scan((acc, curr) => {iter++; return acc + curr}),
    tap(setHtml(`${id}Total`)),
    // it changed only in this object
    tap(val => console.log(`${iter}`))
  );
const predefVar = 100;
const combineTotal$ = combineLatest(addOneClick$('red', predefVar), addOneClick$('black', predefVar))
//I need see chancged predefVar varible here
  .pipe(map(([val1, val2]) => `${val1 + val2} clicked: ${predefVar}`))
  .subscribe(setHtml('total'));

HTML视图

<div>
  <button id='red'>Red</button>
  <button id='black'>Black</button>
</div>
<div>Red: <span id="redTotal"></span> </div>
<div>Black: <span id="blackTotal"></span> </div>
<div>Total: <span id="total"></span> </div>

2 个答案:

答案 0 :(得分:0)

如果要避免使用全局变量,则需要从addOneClick $传递它。

const addOneClick$ = (id, iter) =>
  fromEvent(document.getElementById(id), 'click').pipe(
    mapTo(10),
    startWith(0),
    scan((acc, curr) => {iter++; return acc + curr}),
    map(res=>[res,iter])
    ....
)

答案 1 :(得分:0)

当您在函数中传递原始参数时,该值被复制为其他变量。无论您分配什么,全局变量都不会更改。如果您定义object,则可以解决此问题,因为它作为ref传递,因此可以更改其属性。

如果您将predefVar定义为全局变量,只需直接调用它即可:

var predefVar = 100;

const addOneClick$ = (id) =>
  fromEvent(document.getElementById(id), 'click').pipe(
    mapTo(10),
    startWith(0),
    scan((acc, curr) => {predefVar++; return acc + curr}),
    tap(setHtml(`${id}Total`)),
    // it changed only in this object
    tap(val => console.log(`${iter}`))
  );

但是,根据使用情况,应尽可能避免使用全局变量。在这种情况下,您可以像这样使用纯Rx.js:(playground

const {
  of,
  merge,
  combineLatest,
  fromEvent
} = rxjs;

const {
  scan,
  mapTo,
  startWith,
  tap,
  map,
} = rxjs.operators;

const setHtml = id => val => 
  (document.getElementById(id).innerHTML = val);

const addOneClick$ = (id) =>
  fromEvent(document.getElementById(id), 'click').pipe(
    mapTo(10),
    startWith(0),
    scan((acc, curr) => acc + curr),
    tap(setHtml(`${id}Total`)),
  );

const totalClick$ = (arr$, defaultValue) => 
  merge(...arr$).pipe(
    startWith(defaultValue - arr$.length),
    scan((acc) => acc + 1, defaultValue),
  );

const red$ = addOneClick$('red');
const black$ = addOneClick$('black');
const total$ = totalClick$([red$, black$], 100);

const combineTotal$ = combineLatest(
  total$, red$, black$,  
)
  .pipe(
    map(([total, val1, val2]) => `${val1 + val2} clicked: ${total}`)
  )
  .subscribe(
    setHtml('total')
  );