如何取消MobX flow?求示例及await/async实现方案
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

