繁体   English   中英

如何序列化/反序列化 JS observable?

[英]How to serialize/deserialize a JS observable?

如果我有一个可观察的 stream,使用RxJS或类似的,像这样(大理石图):

----1------2------3--4---|

如何将其序列化为NDJSON之类的格式,以便将其保存在数据库中? 保存后,如何将其重构为可观察对象?

对于上下文,我想在 DOM 中捕获用户操作的 stream(如鼠标拖动等),然后在稍后与用户最初执行的操作完全相同的时间重播它们。

如果时间很重要,您可能希望将时间值与事件本身一起存储。

小POC:

import { fromEvent, Observable, of, timer } from "rxjs";
import {
  map,
  tap,
  mergeMap,
  concatMap,
  takeUntil,
  mapTo
} from "rxjs/operators";

let latestCache: Array<{ time: number; event: MouseEvent }>;

fromEvent(document.getElementById("start-cache"), "click")
  .pipe(
    concatMap(() => {

      const source = fromEvent(window, "mousemove").pipe(
        tap((x: MouseEvent) => console.log(x.clientX, x.clientY)),
        takeUntil(timer(1000)),
        store( newCache => (latestCache = newCache))
      );

      function store(
        onCacheCreated: (
          cache: Array<{ time: number; event: MouseEvent }>
        ) => void
      ) {
        const cache = [];
        let lastTime = Date.now();
        return tap({
          next: (x: MouseEvent) => {
            cache.push({ time: Date.now() - lastTime, event: x });
            lastTime = Date.now();
          },
          complete: () => onCacheCreated(cache)
        });
      }

      return source;
    })
  )
  .subscribe();

fromEvent(document.getElementById("replay-cache"), "click")
  .pipe(
    concatMap(() => {
      if (!latestCache) {
        console.error("no cache yet");
      }
      return of(...latestCache).pipe(
        concatMap(x => timer(x.time).pipe(mapTo(x.event))),
        tap((x: MouseEvent) => console.log(x.clientX, x.clientY))
      );
    })
  )
  .subscribe();
<h1>RxJS playground</h1>

<p>Open the console below to see results</p>

<button id="start-cache">Start Cache </button>
<button id="replay-cache">Replay Cache </button>

https://stackblitz.com/edit/rxjs-vxwurq?file=index.ts

从这里开始,您可以使用 onCacheCreated function 随心所欲地存储数组。

我不确定确切的输入和期望的结果,但一种方法是创建一个可观察对象数组,并将每个可观察对象从 stream 推送到可观察对象数组。

const observableList = [];
observableList.push(userAction$);

从那里,您可以订阅 observable 并将其序列化,然后再将其写入数据库。

forkJoin(observableList).subscribe(res => {
  // console.log(res);
  // save list on database
})

当您想再次阅读它时,您可以使用 RxJS from运算符将其转换为可观察对象,这将允许您在订阅时以确切的顺序发出可观察对象。

暂无
暂无

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

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