使用 RxJS 的某种待办事项列表
Some sort of to-do list with RxJS
我目前在一个 angular 项目中使用 RxJS。在这个项目中,我有一个列表应该作为待办事项列表:
- 一开始,列表中有 5 个项目。
- 用户可以删除元素。
- 删除一个元素时,将获取一个新元素。
- 当列表为空时,获取新元素。
我使用 3 个可观察对象和 1 个状态设法做到了这一点:
// api.fetchElement -> ({ count: number, exclude: string[] }) => Observable<Element[]>
// removedElements$ -> Subject<string>
let elements = []
const initialElements$ = api.fetchElement({ count: 5 })
// removedElementId$ is a subject of string
// in which element ids are produced.
const reloadedElements$ = removedElementId$.pipe(
// My API is eventualy consistent, so I need to exclude the removed items
// for a short period.
mergeMap(id => api.fetchElement({ count: 5, exclude: [ id ] })
)
const reloadedElementsWhenEmptyList$ = interval(3000).pipe(
filter(() => elements.length < 5),
mergeMap(() => api.fetchElement({ count: 5 - elements.length, exclude: elements.map(e => e.id) })
)
initialElements$.subscribe({
next: newElements => elements = newElements
})
reloadedElements$.subscribe({
next: newElements => elements = newElements
})
reloadedElementsWhenEmptyList$.subscribe({
next: newElements => elements = newElements
})
当前的实现有效,但我想知道是否有一种方法可以执行相同的行为,但不必在可观察运算符中使用最终状态 elements
?
我在 RxJS 文档中搜索了运算符,但没有找到满足我需要的任何运算符或运算符组合。
你的设置有点奇怪,我不禁想知道是否有更好的方法来构建它。可悲的是,这里知道的还不够。
无论哪种方式,您都可以通过创建一个在订阅时发出最新 elements
数组的可观察对象来摆脱全局状态 elements
。在这个示例实现中,我将其命名为 elements$
const initialElements$ = api.fetchElement({ count: 5 });
// removedElementId$ is a subject of string
// in which element ids are produced.
const reloadedElements$ = removedElementId$.pipe(
// My API is eventualy consistent, so I need to exclude the removed items
// for a short period.
mergeMap(id => api.fetchElement({
count: 5,
exclude: [ id ]
}))
);
const reloadedElementsWhenEmptyList$ = interval(3000).pipe(
switchMap(_ => elements$),
filter(elements => elements.length < 5),
mergeMap(elements => api.fetchElement({
count: 5 - elements.length,
exclude: elements.map(e => e.id)
}))
);
const elements$ = merge(
initialElements$,
reloadedElements$,
reloadedElementsWhenEmptyList$
).pipe(
startWith([]),
shareReplay(1)
);
您会注意到,当我需要访问您的旧元素数组时,我只是订阅了 elements$
。
如果您使用的是 TypeScript,可能需要一些额外的工作来确保您的类型在此处对齐。同样,您的示例中没有足够的信息来执行此操作,但我会把这个练习留给您。
我目前在一个 angular 项目中使用 RxJS。在这个项目中,我有一个列表应该作为待办事项列表:
- 一开始,列表中有 5 个项目。
- 用户可以删除元素。
- 删除一个元素时,将获取一个新元素。
- 当列表为空时,获取新元素。
我使用 3 个可观察对象和 1 个状态设法做到了这一点:
// api.fetchElement -> ({ count: number, exclude: string[] }) => Observable<Element[]>
// removedElements$ -> Subject<string>
let elements = []
const initialElements$ = api.fetchElement({ count: 5 })
// removedElementId$ is a subject of string
// in which element ids are produced.
const reloadedElements$ = removedElementId$.pipe(
// My API is eventualy consistent, so I need to exclude the removed items
// for a short period.
mergeMap(id => api.fetchElement({ count: 5, exclude: [ id ] })
)
const reloadedElementsWhenEmptyList$ = interval(3000).pipe(
filter(() => elements.length < 5),
mergeMap(() => api.fetchElement({ count: 5 - elements.length, exclude: elements.map(e => e.id) })
)
initialElements$.subscribe({
next: newElements => elements = newElements
})
reloadedElements$.subscribe({
next: newElements => elements = newElements
})
reloadedElementsWhenEmptyList$.subscribe({
next: newElements => elements = newElements
})
当前的实现有效,但我想知道是否有一种方法可以执行相同的行为,但不必在可观察运算符中使用最终状态 elements
?
我在 RxJS 文档中搜索了运算符,但没有找到满足我需要的任何运算符或运算符组合。
你的设置有点奇怪,我不禁想知道是否有更好的方法来构建它。可悲的是,这里知道的还不够。
无论哪种方式,您都可以通过创建一个在订阅时发出最新 elements
数组的可观察对象来摆脱全局状态 elements
。在这个示例实现中,我将其命名为 elements$
const initialElements$ = api.fetchElement({ count: 5 });
// removedElementId$ is a subject of string
// in which element ids are produced.
const reloadedElements$ = removedElementId$.pipe(
// My API is eventualy consistent, so I need to exclude the removed items
// for a short period.
mergeMap(id => api.fetchElement({
count: 5,
exclude: [ id ]
}))
);
const reloadedElementsWhenEmptyList$ = interval(3000).pipe(
switchMap(_ => elements$),
filter(elements => elements.length < 5),
mergeMap(elements => api.fetchElement({
count: 5 - elements.length,
exclude: elements.map(e => e.id)
}))
);
const elements$ = merge(
initialElements$,
reloadedElements$,
reloadedElementsWhenEmptyList$
).pipe(
startWith([]),
shareReplay(1)
);
您会注意到,当我需要访问您的旧元素数组时,我只是订阅了 elements$
。
如果您使用的是 TypeScript,可能需要一些额外的工作来确保您的类型在此处对齐。同样,您的示例中没有足够的信息来执行此操作,但我会把这个练习留给您。