Javascript 两个观测值之间的差异
假设我有两个观测值 第一个可观察到的是特定列表的数组:Javascript 两个观测值之间的差异,javascript,angular,firebase,rxjs,angular6,Javascript,Angular,Firebase,Rxjs,Angular6,假设我有两个观测值 第一个可观察到的是特定列表的数组: [ {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',
[
{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
]
第二个可观察到的是一组被忽略的列表:
[
{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
]
结果应该是一个新的可观察列表(第一个可观察列表),但不能有任何被忽略的列表:
[
{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(?));
我没有测试,但我认为应该可以:
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))
})
)
CombineTest(值$,排除$).pipe(
映射(([值,排除])=>{
//将所有排除的ID放入映射以获得更好的性能
const excludedIds:Map=excluded.reduce(
(附件:地图,项目)=>{
附件组(项目id,未定义)
返回acc;
},
新地图()
);
//通过查找当前
//item.id是否在排除列表中
返回值.filter(item=>!excludedIds.has(item.id))
})
)
说明:
使用combinelatetest
无论从何处获得更新,您都会收到警告。如果您在示例中使用with latestfrom
,则仅当更新了值$
可观察值时,才会触发更新。但是,如果排除的$
发生更改,则不会在您的案例中触发更新
然后将所有被排除的ID放入一个映射而不是数组中,因为我们需要知道是否应该排除给定的ID。查看地图比查看数组快得多
然后只需过滤值数组。如果我理解正确,您需要做的是
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);
import{BehaviorSubject,combinelateest,of,observeable}来自“rxjs”;
从“rxjs/operators”导入{delay,map,scan,concatMap};
/**
*数据源
*/
//只是为了展示的目的。。。模拟随时间发射的项目
const simulatedEmitOverTime=()=>(来源:可观察)=>
源管道(
concatMap(thing=>of(thing).pipe(延迟(Math.random()*1000)))
);
接口事物{
id:字符串;
}
//随时间推移的事物流
const thingsOverTime$=的(
{id:“zzz”},
{id:“aaa”},
{id:“007”}
).烟斗(
模拟线粒体()
);
//随着时间的推移,被忽视的事物不断涌现
const IgnoredThings加班$=的(
{id:“007”},
{id:“zzz”}
).烟斗(
模拟线粒体()
);
/**
*在你的应用程序中的某个地方
*/
//聚合传入的东西
//'scan'采用减速机类型函数
const aggregatedThings$=thingsOverTime$.pipe(
扫描(
(聚合的things:Thing[],incomingThing:Thing)=>
聚合的总含量(收入),
[]
)
);
//从传入的忽略对象ID创建一个集合
//一个集合将允许随着时间的推移轻松过滤
const ignoredIds$=ignoredThings加班$.pipe(
扫描(
(不包括didset,incomingThing:Thing)=>
excludedIdSet.add(incomingThing.id),
新集合()
)
);
//合并流,然后过滤掉被忽略的ID
const sanitizedThings$=组合测试(聚合Things$,ignoredIds$)
.烟斗(
map(([things,ignored])=>things.filter({id})=>!ignored.has(id)))
);
//在需要的地方订阅
//注:最终结果将根据项目进入的时间而有所不同
//随着时间的推移(此处正在模拟)
sanitizedThings$.subscribe(console.log);
如果列表在第一个可观察对象上发出,然后在第二个可观察对象上作为忽略列表发出,该怎么办?你能保证不会发生这种情况吗?另外,由于你显然需要缓冲第二个可观察对象,你希望缓冲区永远存在(并增长)还是有条件再次删除它们(即,任何列表只能在第一个可观察对象中出现一次,基于时间的…)?