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

如何取消MobX flow?求示例及await/async实现方案

Fixing MobX Async Action Cancellation: Flow vs Async/Await

Hey there! Let's work through your cancellation issue step by step, and give you the async/await example you're looking for.

Why cancel() Isn't Working for You

First, let's diagnose the problem:
You're storing the result of flow().then(...) in this._fetchRawEguide, but that value is a native JavaScript Promise—and native Promises don't have a cancel() method at all.

MobX's flow does return a special object with a cancel() method, but as soon as you chain .then() onto it, you convert that object into a standard Promise, losing access to the cancel functionality.

Quick Fix for Flow Usage

If you want to keep using flow, just store the original return value of the flow action instead of the chained Promise:

componentDidMount() {
  // Store the flow object directly, not the then() result
  this._fetchFlow = this.props.combinedEguide.fetchRawEguide(null, true);
  this._fetchFlow.then(() => {
    this._fetchFlow = null;
    this.setState({ loaded: true });
  });
}

componentWillUnmount() {
  if (this._fetchFlow) {
    this._fetchFlow.cancel(); // Now this works!
    this._fetchFlow = null;
  }
}

Async/Await Version with Cancellation

If you prefer to use async/await instead of generators/flow, you'll need to use the AbortController API (supported in all modern browsers and Node.js) to handle cancellation. This is the standard way to cancel async operations in JavaScript now.

Step 1: Update the MobX Action

Modify your action to accept an AbortSignal and use it to cancel the underlying request:

import { action } from "mobx";

@action fetchRawEguide = async (date, redirectOnError = false, signal) => {
  try {
    // Pass the signal to your request (works with fetch, axios 0.22+, etc.)
    const res = await request(/* your request params */, { signal });
    
    // Rest of your logic here...
  } catch (err) {
    // Ignore the abort error so it doesn't trigger unwanted error handling
    if (err.name === "AbortError") return;
    
    // Handle other errors as before
    if (redirectOnError) {
      // Your redirect logic here
    }
  }
};

Step 2: Use the Action in Your Component

Create an AbortController in your component, pass its signal to the action, and call abort() when unmounting:

componentDidMount() {
  this._abortController = new AbortController();
  const { signal } = this._abortController;

  this.props.combinedEguide.fetchRawEguide(null, true, signal)
    .then(() => {
      this.setState({ loaded: true });
    })
    .catch(err => {
      // Skip abort errors
      if (err.name !== "AbortError") {
        // Handle unexpected errors here
      }
    });
}

componentWillUnmount() {
  if (this._abortController) {
    // Cancel the async operation
    this._abortController.abort();
    this._abortController = null;
  }
}

Notes for Custom Request Libraries

If you're using a custom request function that doesn't support AbortSignal out of the box, you can add a check for the signal's aborted property before proceeding with async steps:

async function customRequest(url, options) {
  if (options?.signal?.aborted) {
    throw new DOMException("Request aborted", "AbortError");
  }
  
  // Your request logic...
  
  // Check signal again before resolving if needed
  if (options?.signal?.aborted) {
    throw new DOMException("Request aborted", "AbortError");
  }
  
  return response;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:46:49