Как сериализовать / десериализовать наблюдаемый JS? - PullRequest
0 голосов
/ 04 ноября 2019

Если у меня есть наблюдаемый поток, использующий RxJS или аналогичный, например, (диаграмма * мрамор ):

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

Как я могу сериализовать это вформат как NDJSON чтобы я мог сохранить его в базе данных? Как только он будет сохранен, как я могу восстановить его как наблюдаемый?

Для контекста я хочу захватить поток действий пользователя в DOM (например, перетаскивание мышью и т. Д.), А затем воспроизвести их позднее. точно так же, как пользователь изначально выполнил это.

1 Ответ

1 голос
/ 04 ноября 2019

Если время имеет значение, вы можете сохранить значение времени вместе с самими событиями.

Little 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.

...