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); } } } }
问题原因与解决方法
核心问题
代码存在两个关键问题导致多次回调失效:
- Promise的局限性:Promise只能被resolve/reject一次,无法接收多次返回值,不适合多次回调场景。
- 同步循环的问题: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
相关产品推荐
相关产品推荐

