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

XState服务中无法调用类内方法,全局方法运行正常?

为何XState服务的actions中无法调用类内声明的方法,全局方法却能正常运行?

问题概述

在LoaderMachine类中,XState服务的actions配置里的fetch方法尝试调用类内的fetchDataInsideClass时触发编译错误,但调用类外的全局方法fetchData却能正常执行。

代码示例

export class LoaderMachine {
    service = interpret(createMachine<LoaderContext, LoaderEvent, LoaderState>(
        {
        .....
        }, {
            actions: {
                fetch() {
                    this.fetchDataInsideClass(); // 无法调用
                    fetchData(); // 全局方法可正常运行
                },
                restart() {
                    console.log('Recovering from error')
                    service.send('RESTART');
                },
                finished(context, event) {
                    console.log('Done');
                }
            }
        }));

    async fetchDataInsideClass() {
        try {
            console.log('Started');
            service.send('SUCCESS');
        } catch (err) {
            console.error(`Failed with ${err}`);
            service.send('ERROR');
        }
    }
}

async function fetchData() {
    try {
        console.log('Started');
        service.send('SUCCESS');
    } catch (err) {
        console.error(`Failed with ${err}`);
        service.send('ERROR');
    }
}

编译错误信息

TS2349: This expression is not callable.
Not all constituents of type 'AssignActionObject<LoaderContext, LoaderEvent> | ActionObject<LoaderContext, LoaderEvent> | ActionFunction<...>' are callable.     
Type 'AssignActionObject<LoaderContext, LoaderEvent>' has no call signatures

原因分析

  1. this指向异常:XState执行actions中的普通函数时,函数内部的this并不会指向LoaderMachine的实例,而是指向XState内部的执行上下文(或严格模式下为undefined)。此时this.fetchDataInsideClass根本不是类中定义的方法,自然无法调用。
  2. 类型不匹配:TypeScript检测到this.fetchDataInsideClass不符合XState Action的类型要求,因此抛出类型错误。
  3. 全局方法能运行的原因:全局方法fetchData不依赖类实例的this,直接访问全局作用域中的service(尽管这种写法存在隐患,正确的做法应该是使用类实例的service),所以能正常执行。

解决方案

方案1:使用箭头函数绑定this

箭头函数会捕获外层作用域的this(即LoaderMachine的实例),修改actions中的fetch方法为箭头函数:

actions: {
    fetch: () => {
        this.fetchDataInsideClass(); // 此时this指向类实例
    },
    // 其他action保持不变
}

方案2:修正类内方法的service访问

同时,类内的fetchDataInsideClass方法中应该使用类实例的service,而不是全局service,避免作用域问题:

async fetchDataInsideClass() {
    try {
        console.log('Started');
        this.service.send('SUCCESS'); // 使用this.service
    } catch (err) {
        console.error(`Failed with ${err}`);
        this.service.send('ERROR');
    }
}

方案3:在构造函数中绑定this

如果偏好使用普通函数,可以在类的构造函数中手动绑定this:

export class LoaderMachine {
    service;

    constructor() {
        this.fetch = this.fetch.bind(this);
        this.service = interpret(createMachine<LoaderContext, LoaderEvent, LoaderState>(
            {
            .....
            }, {
                actions: {
                    fetch: this.fetch,
                    // 其他action
                }
            }));
    }

    fetch() {
        this.fetchDataInsideClass();
    }

    // 其他方法...
}

内容的提问来源于stack exchange,提问作者Leos Literak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 05:20:28