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

异步TypeScript运行时出现'callbackSuccess is not a function'错误的修复方案咨询

异步TypeScript运行时出现'callbackSuccess is not a function'错误的修复方案咨询

看起来你遇到的问题核心是:api.call的内部实现对回调函数的存在性有依赖,当用户没有显式传入回调时,它会尝试调用一个未定义的callbackSuccess函数,导致报错。我们可以通过修改eval包装的自执行函数,对api.call做一层透明的封装,自动处理回调缺失的情况,完全不用用户手动添加回调。

问题根源分析

从报错和你的测试结果来看,api.call的设计应该是双模式兼容:

  • 如果最后一个参数是函数,就用回调模式执行,调用这个函数返回结果
  • 如果没有传入回调,它可能期望用全局的callbackSuccess/callbackError来处理结果,或者内部没有正确处理Promise的resolve逻辑,导致找不到回调函数报错

而你观察到的“部分请求成功、部分失败”的随机现象,大概率是api.call内部的同步/异步分支逻辑导致的:比如小数据量可能同步执行,刚好绕过了回调检查;大数据量异步执行时,就会触发未定义的callbackSuccess。


最优修复方案:包装api.call为Promise优先的方法

我们可以在eval的自执行函数里,先对api.call做一层代理包装,自动补全回调并转化为Promise,同时兼容原有的回调写法。这样用户既可以用现代的await语法直接获取结果,也可以保留原有的回调写法,完全不需要修改自己的脚本。

修改后的eval代码如下:

eval(`(async (api) => { 
  // 保存原始的api.call方法
  const originalCall = api.call;
  
  // 重写api.call,自动处理回调缺失的情况
  api.call = function(...args) {
    // 检查用户是否传入了回调函数(最后一个参数是函数)
    const hasCallback = typeof args[args.length - 1] === 'function';
    
    if (hasCallback) {
      // 如果有回调,直接调用原始方法,保持原有行为
      return originalCall.apply(this, args);
    } else {
      // 如果没有回调,返回一个Promise,手动绑定success/error回调
      return new Promise((resolve, reject) => {
        // 给参数列表添加我们自己的成功/失败回调
        args.push(
          (data) => resolve(data), // 成功时resolve Promise
          (error) => reject(error) // 失败时reject Promise
        );
        // 调用原始的api.call
        originalCall.apply(this, args);
      });
    }
  };

  try { 
    // 执行用户的脚本,现在用户可以直接用await获取结果
    await ${script};
  } catch (error) { 
    console.error('脚本执行错误:', error); 
  } 
})(api);`);

方案说明

  1. 完全透明的封装:用户的脚本不需要做任何修改,原来的api.call(...)写法可以直接用,加上await就能拿到结果:
    // 用户现在可以这么写,不用加回调
    const result = await api.call("Get", { 
      "typeName": "TYPENAME", 
      "fromDate": "2025-06-11T04:00:00.000Z", 
      "toDate": "2025-06-12T03:59:59.000Z" 
    });
    console.log(result); // 直接拿到数据
    
  2. 兼容原有回调写法:如果用户习惯用回调,原来的代码依然可以正常运行,不会有任何影响
  3. 解决随机报错问题:不管api.call内部是同步还是异步执行,我们都手动传入了合法的回调函数,彻底避免callbackSuccess is not a function的报错

备选方案:注入全局的callbackSuccess函数

如果api.call的内部实现是硬编码依赖全局的callbackSuccess函数(而不是通过参数传递),我们可以在eval的上下文中临时注入这个函数,用完再清理:

eval(`(async (api) => { 
  // 临时注入全局的回调函数
  globalThis.callbackSuccess = (data) => {
    // 这里可以把数据赋值到你期望的地方,比如某个全局变量,或者直接打印
    console.log('自动捕获的返回结果:', data);
    // 如果需要让用户的脚本能拿到数据,可以把data挂载到api对象上,比如api.lastResult = data
  };
  globalThis.callbackError = (error) => {
    console.error('自动捕获的请求错误:', error);
  };

  try { 
    await ${script};
  } catch (error) { 
    console.error('脚本执行错误:', error); 
  } finally {
    // 用完清理,避免污染全局环境
    delete globalThis.callbackSuccess;
    delete globalThis.callbackError;
  }
})(api);`);

注意:这个方案的局限性比较大,因为它只能捕获结果但无法让用户的脚本直接通过const result = api.call(...)拿到数据,更适合临时调试,优先推荐第一种Promise包装方案。


为什么这个方案能解决你的问题?

通过包装api.call,我们强制所有调用都有合法的回调函数:

  • 当用户没传回调时,我们自动添加了绑定到Promise的回调,从根源上避免了callbackSuccess未定义的报错
  • 同时把api.call转化为支持await的Promise方法,符合现代JavaScript的开发习惯,用户的代码会更简洁

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 10:55:30