典型问题:

  • cordova.exec 调用后毫无反应,不进 success 也不进 error。
  • 控制台提示 Class not found / Service not available 等错误。
  • ArkTS 插件 execute 明明被调用了,但 JS 侧拿不到结果。

本文聚焦 插件调用失败与回调调试,带你从 JS → Cordova → ArkTS 三层排查问题。


1. 从一行 cordova.exec 看调用链

在 Web 端,一个典型的原生调用大致长这样:

cordova.exec(success, fail, 'GamePlugin', 'toast', [{ message: '新纪录:2048' }]);

对应到三层结构:

GamePlugin(ArkTS) Cordova Core cordova.exec Web(app.js) GamePlugin(ArkTS) Cordova Core cordova.exec Web(app.js) exec(success, fail, 'GamePlugin', 'toast', args) 组装消息并转发 execute('toast', args, CallbackContext) cb.success()/cb.errorByString() 回传结果 success(result) 或 fail(error)

任何一步出问题,都会表现为“插件调用失败”或“回调不触发”。


2. Web 端:先确认 exec 调用是否正确

2.1 service/action/参数

  • service:必须与 ArkTS 侧注册的 pluginName 一致。
  • action:需要在插件 execute 中有对应分支。
  • args:一个数组,内部可放对象或基本类型。

假设 ArkTS 侧注册了:

cordovaPlugs: Array<PluginEntry> = [
  { pluginName: 'GamePlugin', pluginObject: new GamePlugin() }
];

那么 Web 侧就必须用:

cordova.exec(success, fail, 'GamePlugin', 'toast', [{ message: 'Hi' }]);

2.2 Web 端常见错误

  • service 名字大小写不一致,例如写成 'gamePlugin'
  • action 名字拼错,如 ArkTS 中是 'toast',JS 中写成 'showToast'
  • fail 回调未传,导致即使有错误也不知道。

建议在调用处增加基础日志:

cordova.exec(function () {
  console.log('[JS] GamePlugin.toast success');
}, function (err) {
  console.error('[JS] GamePlugin.toast error:', err);
}, 'GamePlugin', 'toast', [{ message: msg }]);

3. ArkTS 插件:execute 分支与 CallbackContext

3.1 execute 的基本结构

在 ArkTS 插件中,通常会实现:

export class GamePlugin extends CordovaPlugin {
  execute(action: string, args: ESObject[], cb: CallbackContext): boolean {
    if (action === 'toast') {
      const msg = String(args?.[0]?.['message'] ?? args?.[0] ?? '');
      const ui = this.cordovaWebView?.getUIContext();
      if (ui) {
        ui.getPromptAction().showToast({ message: msg });
        cb.success();
      } else {
        cb.errorByString('no ui context');
      }
      return true;
    }
    return false;
  }
}

3.2 execute 返回值的含义

  • 返回 true
    • 表示该插件 已经处理 了该 action,Core 不会再尝试其它插件;
    • 不一定表示“业务成功”,成功/失败要以 cb.success/cb.error* 为准。
  • 返回 false
    • 表示“我不处理这个 action”,Core 可能会认为找不到对应方法。

常见坑:

  • execute 中逻辑报错抛异常,但没有任何 try/catch,导致 callback 没被调用,JS 侧等待无果。
  • 忘记返回 true,导致 Core 认为插件未处理该 action,抛出类似 Class/Action not found 的错误。

3.3 加日志定位 action 分支

为了确定 execute 有没有被调用,可以在开始处打日志:

execute(action: string, args: ESObject[], cb: CallbackContext): boolean {
  console.log('[GamePlugin] execute action=', action, ' args=', JSON.stringify(args));
  // ... 后续分支
}

如果日志中没有出现对应 action,说明问题发生在 JS → Core 路径上,而不是插件本身。


4. 典型问题场景与排查

场景 1:Service not found / Class not found

现象

  • 控制台报错:
    • Class not found GamePlugin 或类似信息。

排查步骤

  1. 确认 ArkTS 中的 pluginName

    cordovaPlugs: Array<PluginEntry> = [
      { pluginName: 'GamePlugin', pluginObject: new GamePlugin() }
    ];
    
  2. 确认 JS 中 service 参数完全一致(大小写也要一致)。

  3. 若使用多 webId、多页面,需要确认插件注册的 webId 与当前页面对应。

场景 2:execute 能打印日志,但 JS 侧 success/fail 都没进

高概率原因

  • execute 中没有调用 callback。
  • callback 在某些分支中被遗漏。

示例对比

// ❌ 不完整:某些路径缺少回调
if (action === 'toast') {
  if (!ui) {
    console.error('no ui');
    return true; // 忘了 cb.error
  }
  ui.getPromptAction().showToast({ message: msg });
  // 忘了 cb.success
  return true;
}

应改为:

if (!ui) {
  console.error('no ui');
  cb.errorByString('no ui context');
  return true;
}
ui.getPromptAction().showToast({ message: msg });
cb.success();
return true;

场景 3:JS 侧 error 回调触发,但信息很难看懂

建议在 ArkTS 中对错误进行更友好的包装:

cb.errorByString('[GamePlugin] no ui context');

这样 JS 侧收到的错误信息更易排查定位。


5. 调试套路:从 JS 日志到 ArkTS 日志

为了系统调试插件调用问题,可以建立如下日志链路:

JS 调用处 console.log

cordova.exec 内部日志

Cordova Core 日志

ArkTS 插件 execute 日志

JS success/fail 回调日志

建议实践

  • JS 调用前:

    console.log('[JS] call GamePlugin.toast, msg=', msg);
    
    
  • ArkTS execute 内部:

    console.log('[GamePlugin] execute action=', action, ' args=', JSON.stringify(args));
    
    
  • callback 前:

    console.log('[GamePlugin] toast done, will cb.success');
    
    
  • JS success/fail 回调里:

    console.log('[JS] GamePlugin.toast success');
    console.error('[JS] GamePlugin.toast error=', err);
    
    

通过对比这几层日志,就能判断问题落在哪一层:

  • JS 有调用日志,ArkTS 没有 → Core 路径或 service/action 配置有问题。
  • ArkTS 有日志,JS 没有回调 → callback 调用有问题。
  • 两边都有 → 可能是 JS 业务逻辑对结果的处理有 bug。

6. 完整排查流程图

最后,用一张流程图归纳插件调用失败时的排查顺序:

cordova.exec 无反应/报错

JS 日志中有调用记录吗?

检查调用代码是否执行/条件分支

ArkTS execute 中有日志吗?

检查 service/action/插件注册

execute 内是否调用 cb.success/cb.error?

补全所有分支的 callback 调用

JS 是否收到 success/fail?

检查 Core 层桥接/异常

检查 JS 后续业务逻辑

掌握这套“从 exec 到 callback”的调试思路后,你在 HarmonyOS + Cordova 项目中开发更多插件时,就不会被“插件没反应”之类的问题困住,可以有条不紊地定位到具体层级和代码行。

欢迎加入开源鸿蒙PC社区:https://harmonypc.csdn.net/

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐