您将如何在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应该发出2个值:
乐观价值
来自ajax结果的值
注意:
乐观值不应触发ajax调用。
乐观值应该能够使用来自可观察的
todoIdSource
源的数据。在RxJS中是否有一种完美的方法来完成此任务?我可以想象引入第二个Observable
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方法。
stackblitz
小附录:我假设订阅者实际上只对当前状态感兴趣。
您可以添加另一个
scan((acc,todo) =>({...acc,...{[todo.id]:todo}}), {}),
map(v => Object.keys(v).map(k => v[k])),
为此,请参见addendum stackblitz