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

Ionic6+Cordova11中Cordova回调无法多次执行的解决方法

Ionic-Cordova 多次回调失效问题解决

我在开发Ionic 6 + Cordova 11项目时,需要实现Cordova插件的多次回调,但设置pluginResult.setKeepCallback(true)后并未生效。以下是我的代码实现:

组件代码

let data = JSON.parse(JSON.stringify(this.someOptions)) 
this.customService.TestFunction(data).then(response => {
  console.log(response);
})
.catch(ex => {
  // console.log(ex)
})

自定义服务代码

TestFunction(arg1: any): Promise<any> {
    var temp = cordova(this, "TestFunction", { callbackStyle: "object" }, [arg1]);
    return temp
}

JS层代码

exports.TestFunction = function (arg0, success, error) {
    exec(success, error, 'SomeCordovaPlugin', 'TestFunction', [arg0]);
};

Android端Java代码

public class SomeCordovaPlugin extends CordovaPlugin {

  private CallbackContext testCallbackContext;

  @Override
  public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
       if (action.equals("TestFunction")) {
           this.TestFunction(args, callbackContext);
           return true;
       }
       return false;
  }

  private void TestFunction(JSONArray args, CallbackContext callbackContext) {
     testCallbackContext=callbackContext;
     if (args != null) {
       try {
           for(int i=0;i<7;i++){
                 PluginResult pluginResult = new PluginResult(PluginResult.Status.OK ,testCallbackContext.getCallbackId());
                 pluginResult.setKeepCallback(true); // keep callback
                 testCallbackContext.sendPluginResult(pluginResult);  
            }
          } catch (Exception ex) {
                 testCallbackContext.error("An error occured:" + ex);
                }
     }
  }

}

问题原因与解决方法

核心问题

代码存在两个关键问题导致多次回调失效:

  1. Promise的局限性:Promise只能被resolve/reject一次,无法接收多次返回值,不适合多次回调场景。
  2. 同步循环的问题:Java层同步循环发送回调,可能导致Cordova回调机制未正确处理所有请求,且没有给前端留出接收间隔。

修正步骤

1. 改用回调函数替代Promise封装

放弃Promise,使用传统回调函数模式来接收多次返回结果:

修改自定义服务代码:

TestFunction(arg1: any, successCallback: (data: any) => void, errorCallback: (error: any) => void): void {
    cordova(this, "TestFunction", { callbackStyle: "node" }, [arg1], successCallback, errorCallback);
}

修改组件代码:

let data = JSON.parse(JSON.stringify(this.someOptions)) 
this.customService.TestFunction(
  data,
  (response) => {
    console.log(response);
    // 处理每次回调的结果
  },
  (ex) => {
    // 处理错误
  }
);

2. 调整Java层回调发送逻辑

  • 确保setKeepCallback仅在非最后一次回调时设为true,最后一次回调后释放上下文。
  • 用异步延迟的方式模拟真实场景的多次回调,避免同步循环的问题:

修改Android端Java代码:

import android.os.Handler;
import android.os.Looper;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;

public class SomeCordovaPlugin extends CordovaPlugin {

  private CallbackContext testCallbackContext;
  private int callbackCount = 0;
  private static final int MAX_CALLBACKS = 7;

  @Override
  public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
       if (action.equals("TestFunction")) {
           this.testCallbackContext = callbackContext;
           this.startSendingCallbacks();
           return true;
       }
       return false;
  }

  private void startSendingCallbacks() {
      new Handler(Looper.getMainLooper()).postDelayed(() -> {
          if (callbackCount < MAX_CALLBACKS) {
              try {
                  // 替换为实际要返回的业务数据
                  String result = "第" + (callbackCount + 1) + "次回调结果";
                  PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, result);
                  // 最后一次回调后不再保持上下文
                  pluginResult.setKeepCallback(callbackCount < MAX_CALLBACKS - 1);
                  testCallbackContext.sendPluginResult(pluginResult);
                  callbackCount++;
                  startSendingCallbacks(); // 递归实现多次异步回调
              } catch (Exception ex) {
                  testCallbackContext.error("发生错误:" + ex.getMessage());
              }
          }
      }, 1000); // 每隔1秒发送一次回调
  }
}

3. JS层代码保持不变

现有JS层代码已正确传递success/error回调,无需修改。

关键说明

  • 回调函数模式:多次回调场景下必须使用传统回调函数,Promise不支持多次返回值。
  • setKeepCallback的作用:设为true时Cordova会保留回调上下文,允许后续继续发送结果;最后一次回调设为false释放资源。
  • 异步发送:用Handler延迟发送模拟真实场景(如传感器数据、状态变化),避免同步循环导致前端无法正确接收所有回调。

内容的提问来源于stack exchange,提问作者Halil Polat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 16:21:10