Разница между двумя наблюдаемыми - PullRequest
0 голосов
/ 27 мая 2018

Допустим, у меня есть две наблюдаемые.

Первая наблюдаемая - это массив определенных списков:

[
    {id: 'zzz', other props here...},
    {id: 'aaa', ...},
    {id: '007', ...}
    ... and more over time
]

Вторая наблюдаемая - это массив игнорируемых списков:

[
    {id: '007'}, // only id, no other props
    {id: 'zzz'}
    ... and more over time
]

Результатом должно быть новое наблюдаемое списков (первое наблюдаемое), но не должно быть ни одного из игнорируемых списков:

[
    {id: 'aaa', other props here...}
    ... and more over time
] 

Это то, что я сейчас имею перед публикацией:

obs2.pipe(withLatestFrom(obs1, ? => ?, filter(?));

Ответы [ 2 ]

0 голосов
/ 27 мая 2018

Если я правильно понимаю, вам нужно будет

  1. Агрегировать входящие элементы по времени
  2. Агрегировать идентификаторы, которые должны игнорироваться с течением времени
  3. Наконец, поскольку оба вышеперечисленных потока излучают со временем, генерируют результирующий список элементов, которые не включают игнорируемые идентификаторы.

Учитывая вышеизложенное, ниже приведен грубый примерты можешь попробоватьКак отмечалось ниже, вы получите разные результаты в зависимости от частоты первых двух потоков, потому что именно так и происходит с асинхронным.Чтобы показать это, я имитирую случайную задержку передачи вещей во времени.

Надеюсь, это поможет!

PS: ниже приведен Typescript, предполагая, что rxjs@^6.

import { BehaviorSubject, combineLatest, of, Observable } from "rxjs";
import { delay, map, scan, concatMap } from "rxjs/operators";

/**
 * Data sources
 */

// Just for showcase purposes... Simulates items emitted over time
const simulatedEmitOverTime = <T>() => (source: Observable<T>) =>
  source.pipe(
    concatMap(thing => of(thing).pipe(delay(Math.random() * 1000)))
  );

interface Thing {
  id: string;
}

// Stream of things over time
const thingsOverTime$ = of(
  { id: "zzz" },
  { id: "aaa" },
  { id: "007" }
).pipe(
  simulatedEmitOverTime()
);

// Stream of ignored things over time
const ignoredThingsOverTime$ = of(
  { id: "007" },
  { id: "zzz" }
).pipe(
  simulatedEmitOverTime()
);


/**
 * Somewhere in your app
 */

// Aggregate incoming things
// `scan` takes a reducer-type function
const aggregatedThings$ = thingsOverTime$.pipe(
  scan(
    (aggregatedThings: Thing[], incomingThing: Thing) =>
      aggregatedThings.concat(incomingThing),
    []
  )
);

// Create a Set from incoming ignored thing ids
// A Set will allow for easy filtering over time
const ignoredIds$ = ignoredThingsOverTime$.pipe(
  scan(
    (excludedIdSet, incomingThing: Thing) =>
      excludedIdSet.add(incomingThing.id),
    new Set<string>()
  )
);

// Combine stream and then filter out ignored ids
const sanitizedThings$ = combineLatest(aggregatedThings$, ignoredIds$)
  .pipe(
    map(([things, ignored]) => things.filter(({ id }) => !ignored.has(id)))
  );

// Subscribe where needed
// Note: End result will vary depending on the timing of items coming in
// over time (which is being simulated here-ish)
sanitizedThings$.subscribe(console.log);
0 голосов
/ 27 мая 2018

Я не проверял это, но я думаю, что все должно быть в порядке:

combineLatest(values$, excluded$).pipe(
  map(([values, excluded]) => {
    // put all the excluded IDs into a map for better perfs
    const excludedIds: Map<string, undefined> = excluded.reduce(
      (acc: Map<string, undefined>, item) => {
        acc.set(item.id, undefined)
        return acc;
      },
      new Map()
    );

    // filter the array, by looking up if the current
    // item.id is in the excluded list or not
    return values.filter(item => !excludedIds.has(item.id))
  })
)

Объяснение:

Используя combineLatest, вы всегда будетебудьте предупреждены независимо от того, где вы получаете обновление.Если вы используете withLatestFrom, как в вашем примере, оно будет запускать обновление, только если обновляется наблюдаемая values$.Но если excluded$ изменится, это не приведет к обновлению в вашем случае.

Затем выведите все исключенные идентификаторы в карту вместо массива, поскольку нам нужно будет знать, должен ли данный идентификатор иметьбыть исключенным или нет.Просмотр карты намного быстрее, чем просмотр массива.

Затем просто отфильтруйте массив значений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...