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
相关产品推荐
相关产品推荐

