Announcement

👇Official Account👇

图片

Welcome to join the group & private message

Article first/tail QR code

Skip to content

exhaustMap

exhaustMap 是这四个高阶映射操作符中比较特殊的一个。它将源 Observable 发出的每个值映射成一个新的内部 Observable,但只有当上一个内部 Observable 完成后,它才会处理下一个源值。如果在一个内部 Observable 正在执行时,源 Observable 发出了新的值,这些新值将被忽略

核心行为:忽略并等待

exhaustMap 的行为就像一个忙碌的工人。当他正在处理一个任务时,他会完全忽略任何新来的任务。只有当他手头的工作完成后,他才会去接下一个新任务。

弹珠图

source:      --a----b----c--|
            map(v => --v1--v2|)

// a 对应的内部 Observable 正在执行时,b 被忽略了
// a 对应的内部 Observable 完成后,c 才被处理

result:      ----a1--a2----c1--c2|

示例:防止重复提交

这是一个 exhaustMap 的经典用例。想象一个登录按钮,我们希望在用户点击后,发起一个登录请求。在这个请求完成之前,我们希望忽略用户的任何后续点击,以防止重复提交表单。

typescript
import { fromEvent } from 'rxjs';
import { exhaustMap, tap } from 'rxjs/operators';
import { ajax } from 'rxjs/ajax';

const loginButton = document.getElementById('login');

fromEvent(loginButton, 'click').pipe(
  tap(() => console.log('Button clicked, attempting to log in...')),
  exhaustMap(() => {
    const credentials = getCredentials(); 
    return ajax.post('/api/login', credentials);
  })
).subscribe(
  response => console.log('Login successful:', response),
  error => console.error('Login failed:', error)
);

在这个例子中,用户第一次点击按钮时,exhaustMap 会发起一个登录请求。在这个请求返回响应(成功或失败)之前,无论用户再点击多少次按钮,tap 会打印日志,但 exhaustMap 会忽略这些点击,不会发起新的登录请求。这是一种非常简单而有效的防止重复提交的方法。

何时使用?

当你希望在一个异步操作完成前,忽略所有来自源 Observable 的新值时,exhaustMap 是完美的选择。

  • 防止重复提交:登录、保存、提交等按钮的点击事件。
  • 处理一次性触发的动画:开始一个动画,在动画结束前忽略所有其他触发信号。

四大高阶操作符总结

操作符行为场景比喻核心用途
mergeMap并发,来一个处理一个任务分发中心处理可以并发进行的异步任务
concatMap排队,按顺序处理纪律严明的队列保证异步任务的顺序性
switchMap切换,只关心最新的喜新厌旧处理只关心最新结果的场景(如搜索)
exhaustMap忽略,直到当前任务完成忙碌的工人防止重复触发(如点击)

上次更新于: