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

RxJS中如何获取Observable最后一次调用结果并取消先前事件?

RxJS: Get Last Observable Result & Cancel Previous Async Requests

Question 1: Which RxJS operator gets the last emitted value of an Observable?

The last() operator is exactly what you need here. It waits for the source Observable to complete, then emits the last value that was emitted. You can also pass an optional predicate if you only want the last value that matches a specific condition.

For example:

// Emits only the final value from the observable
someObservable.pipe(last()).subscribe(lastValue => {
  console.log('Last value received:', lastValue);
});

// Or with a condition: emit the last value where id is greater than 1
someObservable.pipe(last(item => item.id > 1)).subscribe(matchingLastValue => {
  console.log('Last matching value:', matchingLastValue);
});

Question 2: How to only get the last async result and cancel previous events?

For your button click scenario where you want to ignore all pending prior requests and only keep the latest one, switchMap is the ideal operator. Here's the breakdown:

  • switchMap takes each emitted value (your button clicks) and maps it to a new Observable (your makeRequest() call)
  • If a new click comes in before the previous request completes, it unsubscribes from the old Observable (canceling the pending request) and switches to the new one immediately.

Modified Code Example

First, convert your button clicks into an Observable (adjust based on your framework—native DOM, Angular, React, etc.). Then pipe it through switchMap to handle your requests:

import { fromEvent } from 'rxjs';
import { switchMap } from 'rxjs/operators';

// Get your button element (use @ViewChild in Angular if needed)
const requestButton = document.getElementById('your-request-button');

// Turn button clicks into an Observable stream
const buttonClicks$ = fromEvent(requestButton, 'click');

// Use switchMap to cancel old requests and keep only the latest
buttonClicks$
  .pipe(switchMap(() => this.makeRequest()))
  .subscribe(r => {
    console.log('Latest request result:', r);
  });

Why This Fixes Your Issue

In your original code, every button click creates a new, independent subscription to makeRequest(). This means all pending requests keep running and emit results when they finish—even if you've clicked the button multiple times. With switchMap:

  1. A new click triggers an immediate unsubscribe from the previous makeRequest() Observable
  2. The pending timeout for that old request will either be canceled (if you add cleanup logic) or run to completion, but since the observer is unsubscribed, observer.next() won't fire your subscribe callback
  3. Only the latest request's result will reach your subscribe handler

Optional: Add Cleanup to makeRequest

To fully abort pending timeouts when a request is canceled, update your makeRequest function to clear the timeout on unsubscribe:

makeRequest() { 
  return Observable.create((observer) => { 
    let uniqueId = this.uniqueId++; 
    const timeoutId = setTimeout(() => { 
      console.log('[makeRequest] complete request ' + uniqueId); 
      observer.next({ save: true, id: uniqueId }); 
      observer.complete(); 
    }, 5000);

    // Cleanup logic: runs when the observable is unsubscribed
    return () => {
      clearTimeout(timeoutId);
      console.log('[makeRequest] canceled request ' + uniqueId);
    };
  }); 
}

Now when switchMap unsubscribes from an old request, the timeout is cleared entirely—so that request never completes at all.


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:34:34