RxJS乐观更新(强制发出乐观值)



您将如何在RxJS中实现乐观更新?参见此示例:

const todoIdSource: Subject<string> = new Subject();
const $todo = todoIdSource.pipe(
tap(id => {
const optimisticTodo: any = {
userId: 1,
id: id, // Use some value from the source observable
title: "delectus aut autem",
completed: false
};
// TODO force emit optimisticTodo! How? :)
}),
concatMap((id) => ajax('https://jsonplaceholder.typicode.com/todos/' + id)),
map(response => response.response)
);
$todo.subscribe(value => console.log('TODO', value));
todoIdSource.next('1');

在ajax调用完成之前,$todo不会发出。但我希望它在todoIdSource发出后立即发出乐观值。最终$todo应该发出两个值:

  • 乐观值
  • ajax结果的值

注意:

  • 乐观值不应触发ajax调用
  • 乐观值应该能够使用来自源可观测todoIdSource的数据

在RxJS中有一种优雅的方法可以实现这一点吗?我可以想象引入第二个可观测optimisticTodo$,然后将其与$todo合并。但这感觉并不优雅:(

任一

concatMap(id =>
from(ajax("https://jsonplaceholder.typicode.com/todos/" + id)).pipe(
map(response => response.response),
startWith({...})
)
)

请记住,startWith必须是最后一个操作符(或者至少在map之后(。这样可以确保您在那里传递的值不会被映射,在这种情况下,它不应该被映射,因为您使用映射来提取响应。

concatMap(id =>
merge(
of({...}),
from(ajax("https://jsonplaceholder.typicode.com/todos/" + id)).pipe(
map(response => response.response)
)
)
)

两者都实现了相同的目标:

每当todoIdSource发出时,立即发出乐观的todo,并在ajax调用结束时发出实际的todo。

我更喜欢startWith方法。

堆叠式

小补充:我估计订阅者目前只对当前状态感兴趣。

你可以添加另一个

scan((acc,todo) =>({...acc,...{[todo.id]:todo}}), {}),
map(v => Object.keys(v).map(k => v[k])),

为此,请参阅附录stackblitz

您可以使用startWith运算符实现该行为。

最新更新