如何在RxJS中实现乐观更新?(强制触发乐观值发射)
RxJS 优雅实现乐观更新
这个乐观更新的需求在RxJS里其实有非常优雅的实现方式,完全不用额外搞第二个Observable来合并——咱们直接用mergeMap就能把逻辑收拢在一个流里搞定!
优化后的实现代码
import { Subject, of, concat } from 'rxjs'; import { mergeMap, map } from 'rxjs/operators'; import { ajax } from 'rxjs/ajax'; const todoIdSource: Subject<string> = new Subject(); const $todo = todoIdSource.pipe( mergeMap((id) => { // 生成乐观值,直接复用当前id const optimisticTodo = { userId: 1, id: id, title: "delectus aut autem", completed: false }; // 返回一个按顺序发射值的合并流:先乐观值,再真实请求结果 return concat( of(optimisticTodo), // 立即发射乐观值 ajax(`https://jsonplaceholder.typicode.com/todos/${id}`).pipe( map(response => response.response) // 处理ajax返回的真实数据 ) ); }) ); $todo.subscribe(value => console.log('TODO', value)); todoIdSource.next('1');
核心逻辑解释
- 用
mergeMap替代原有的tap+concatMap:mergeMap允许我们为每个输入的id返回一个多值的Observable流,把“生成乐观值”和“发起真实请求”的逻辑统一在一起,不需要拆分到多个流里。 concat保证顺序:concat会先订阅并完成第一个流(of(optimisticTodo)会立即发射乐观值),再订阅第二个流(发起ajax请求并等待返回真实值),完美实现“先乐观更新,后真实同步”的顺序要求。- 完全满足你的约束:乐观值的生成直接使用当前id,且乐观值的发射不会触发ajax请求(ajax请求是独立的第二个流,只会执行一次)。
可选优化
如果需要处理快速连续触发的场景(比如用户多次点击发起请求),可以把mergeMap换成switchMap——这样新的id进来时会自动取消之前未完成的ajax请求,避免无效的网络请求;如果需要保留所有请求的结果,就继续使用mergeMap或者concatMap。
内容的提问来源于stack exchange,提问作者spierala
相关产品推荐
相关产品推荐

