You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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');

核心逻辑解释

  1. 用mergeMap替代原有的tap+concatMap:mergeMap允许我们为每个输入的id返回一个多值的Observable流,把“生成乐观值”和“发起真实请求”的逻辑统一在一起,不需要拆分到多个流里。
  2. concat保证顺序:concat会先订阅并完成第一个流(of(optimisticTodo)会立即发射乐观值),再订阅第二个流(发起ajax请求并等待返回真实值),完美实现“先乐观更新,后真实同步”的顺序要求。
  3. 完全满足你的约束:乐观值的生成直接使用当前id,且乐观值的发射不会触发ajax请求(ajax请求是独立的第二个流,只会执行一次)。

可选优化

如果需要处理快速连续触发的场景(比如用户多次点击发起请求),可以把mergeMap换成switchMap——这样新的id进来时会自动取消之前未完成的ajax请求,避免无效的网络请求;如果需要保留所有请求的结果,就继续使用mergeMap或者concatMap。

内容的提问来源于stack exchange,提问作者spierala

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 20:18:13