When developing Cordoba plugins, all the tutorials I found look something like this:
File: AwesomePlugin.js
var AwesomePlugin = { kungfuGripAction = function(target, successCallback, failureCallback) { return cordova.exec( successCallback, failureCallback, 'AwesomePluginClass', 'kungfuGripAction', [target] ); } }; module.exports = AwesomePlugin;
File: AwesomePluginClass.java
@Override public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { if (ACTION_KUNGFU_GRIP.equals(action)) { JSONObject target = args.getJSONObject(0); if (gripTarget(target)) { callbackContext.success("Target successfully gripped."); return true; } else { callbackContext.error("Could not grip target."); return false; } } Log.d(LOG_TAG, "INVALID ACTION! " + action); callbackContext.error("Invalid action: " + action); return false; }
File: clientCode.js
AwesomePlugin.kungfuGripAction(cobraEnemy, function(ok) { }, function(err) { });
In the above code, callbacks can only be called once and then deleted. If you try to call the .success() or .error() method of the .success() context object, this will not work, and you will receive a log message:
Attempted to send a second callback for ID: AwesomePlugin2982699494<BR>W/CordovaPlugin(976) Result was: "Target successfully gripped."
It seems that it is impossible to write a method with a callback that can be called multiple times, since .success() and .error() are the only documented ways to call a callback from the plugin's own code. While this is basically what we want, there are times when we want the plugin to rerun the callback. For instance:
AwesomePlugin.kungfuGripAction(cobraEnemy, function(ok) { // After successful grip, punch repeatedly and update life meter. AwesomePlugin.punchRepeatedly(cobraEnemy, function(hits) { updateLifeMeter(cobraEnemy, hits); }, function(err) { }); }, function(err) { });
AwesomePlugin.punchRepeatedly() above will be executed repeatedly (possibly in a separate thread) and will call function(hits) with each successful execution. If this is done de facto (using one-time callbacks), you need to either use a loop (which is bad because it is not asynchronous) or the tail call AwesomePlugin.punchRepeatedly() in the callback (error prone).
What would be the correct way to implement punchRepeatedly() in native code so that it can register the callback once and then execute it again?