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

RxJS问题:如何合并初始化API请求与点击/按键Observable

RxJS实现初始化请求+事件触发重新请求的正确方式

你的代码问题出在switchMap中的逻辑判断:of(res) || merge(...)永远会返回of(res),因为Observable对象是真值,导致后续的点击/按键事件流完全不会被触发,所以只能拿到初始化的一次数据。

要实现初始化自动请求,之后点击或按键重新请求的需求,正确的做法是创建一个「触发流」:初始时自动发出一个值触发请求,之后监听点击和按键事件来触发新的请求,再将每个触发信号映射到API请求流上。

修改后的代码如下:

import { fromEvent, merge, of } from 'rxjs';
import { switchMap, catchError } from 'rxjs/operators';
import { fromFetch } from '@rxjs/fetch';

// 定义触发事件:初始触发一次 + 点击/按键事件
const trigger$ = merge(
  of(undefined), // 初始触发信号,用于首次请求
  fromEvent(document, 'click'),
  fromEvent(document, 'keypress')
);

// 封装API请求逻辑,每次调用都会发起新的请求
const fetchData$ = () => fromFetch('https://api.artic.edu/api/v1/artworks/129884')
  .pipe(
    switchMap((response) => {
      if (response.ok) {
        return response.json();
      } else {
        return of({ error: true, message: `Error ${response.status}` });
      }
    }),
    catchError((err) => {
      console.error(err);
      return of({ error: true, message: err.message });
    })
  );

// 订阅触发流,每次触发都发起新请求
trigger$
  .pipe(switchMap(() => fetchData$()))
  .subscribe((art) => {
    if (!art.error) {
      console.log('Fetched ' + art.data.id);
    } else {
      console.log('Request failed:', art.message);
    }
  });

关键改动说明:

  • 将API请求封装成函数fetchData$(),确保每次触发时都会创建新的请求Observable,避免复用旧流导致只请求一次
  • 创建trigger$流,用merge合并初始触发信号和两个事件流,保证页面加载时自动触发第一次请求
  • 用switchMap将每个触发信号映射到新的API请求,每次事件触发会自动取消未完成的旧请求,发起新请求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 06:45:31