0

I have the following observable that gets pages on a workspace:

page$ = this.pageService.getPages(this.workspaceId) // .subscribe() to get data

This is updated periodically when a new page is added.

I want to save the array of pages before and after a new page (or a stream of pages) is added, and then be able to compare them.

For example, on init, if there are three pages, arrayOld would be of the three pages. Then, there would be a new array made, arrayNew, of four pages if one new page was added.

If a page was then deleted, arrayOld would become arrayNew (length of 4), and arrayNew would become the new set of pages (of length 3).

I have yet to find an easy way to accomplish this using subscribe() to the current stream of pages.

Any help here would be amazing. Thank you!

  • 4
    See if `startWith(null)` and `pairWise` will do the trick. https://stackoverflow.com/questions/50059622/rxjs-observable-which-emits-both-previous-and-current-value-starting-from-first – AliF50 Aug 20 '20 at 23:27

3 Answers3

0

Maybe this:

import { Observable, of } from 'rxjs';

const observable = of([1],[1,2], [1],[1,3],[1,3,4],[1,3,4,5]);

let arrayOld = [];
let arrayNew = [];

observable.subscribe(a => {
  arrayOld = JSON.parse(JSON.stringify(arrayNew));
  arrayNew = JSON.parse(JSON.stringify(a));
  
  console.log("---------------");
  console.log("old:", arrayOld);
  console.log("new:", arrayNew);
});

When the pages (deletion and adding) are coded with numbers:

[1]: initially there is only page id=1
[1,2] added page id=2
[1] deleted page id=2
[1,3] added page id=3,
[1,3,4] added page id=4
[1,3,4,5] added page id=5

JSON.parse(JSON.stringify(arrayNew)): is for deep copying arrays

Here is a stackblitz: https://tzb2jv.stackblitz.io

PeterB
  • 960
  • 6
  • 8
0

Use the pairWise operator. Here is an example:

const pages$: Observable<string[]> = of(
  ['Page1', 'Page2', 'Page3'],
  ['Page1', 'Page2', 'Page3', 'Page4'],
  ['Page1', 'Page2', 'Page3', 'Page4', 'Page5'],
);

pages$.pipe(
  startWith([]),
  pairwise(),
).subscribe(
  ([arr1, arr2]) => console.log(arr1, 'changed to', arr2),
);

Output:

[]
changed to
["Page1", "Page2", "Page3"]

["Page1", "Page2", "Page3"]
changed to
["Page1", "Page2", "Page3", "Page4"]

["Page1", "Page2", "Page3", "Page4"]
changed to
["Page1", "Page2", "Page3", "Page4", "Page5"]

MoxxiManagarm
  • 8,735
  • 3
  • 14
  • 43
-1

scan works like a reduce function, you can have an accumulator that returns the previous and current.

const { of } = rxjs;
const { scan } = rxjs.operators;

of([1,2], [1,2], [3, 4], [3, 4]).pipe(
  scan((acc, current) => {
    acc.previous = acc.current;
    acc.current = current;
    return acc;
  }, {})
).subscribe(({ current, previous }) => {
  const added = previous ? current.filter(i => !previous.includes(i)) : current;
  const deleted = previous ? previous.filter(i => !current.includes(i)) : [];
  console.log('Added: ', added);
  console.log('Deleted: ', deleted);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.6.2/rxjs.umd.min.js"></script>
Adrian Brand
  • 20,384
  • 4
  • 39
  • 60