javascript - Cordova重复执行异步方法,会覆盖前一个回调函数?

查看:568
本文介绍了javascript - Cordova重复执行异步方法,会覆盖前一个回调函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

今天遇到个很奇怪的问题,做一个Hybrid App,用的是Cordova,测试机是ipad,本人负责H5部分(因为不会Object-C orz),所以也看不到原生部分的代码。
问题出现在我重复调用一个原生的异步方法,下面直接贴图↓

下面是重复调用的测试代码

结果打印出来的是这样滴↓
"
进来了
出去了
进来了
出去了
第二次成功
"
???我当时就懵逼了,第一次回调哪去了???

解决方案

你为什么要连续调用2次?
Cordova.exec方法执行后,你就等着回调函数的执行,整个过程是异步的~~
异步函数的回调执行要在当前代码块执行完毕后才有可能被执行~~
连续调用2次,后一次的回调函数会覆盖前一次的
看了下exec函数调用逻辑,js会保证每次callback不同,即使同样的方法参数调用:)
而本地java代码调用后回把callbackId传回给JS
JS根据callback再调用相应回调函数

可能是第1次调用本地java代码时候执行出错或超时等原因,而没有返回JS中调用回调函数。而第2次调用时java代码执行成功了,JS回调就被执行....
具体原因要去看插件执行时是否有错误

cordova.js代码片段

...
callbackFromNative: function(callbackId, isSuccess, status, args, keepCallback) {
        try {
            var callback = cordova.callbacks[callbackId];
            if (callback) {
                if (isSuccess && status == cordova.callbackStatus.OK) {
                    callback.success && callback.success.apply(null, args);
                } else if (!isSuccess) {
                    callback.fail && callback.fail.apply(null, args);
                }
                /*
                else
                    Note, this case is intentionally not caught.
                    this can happen if isSuccess is true, but callbackStatus is NO_RESULT
                    which is used to remove a callback from the list without calling the callbacks
                    typically keepCallback is false in this case
                */
                // Clear callback if not expecting any more results
                if (!keepCallback) {
                    delete cordova.callbacks[callbackId];
                }
            }
        }
        catch (err) {
            var msg = "Error in " + (isSuccess ? "Success" : "Error") + " callbackId: " + callbackId + " : " + err;
            console && console.log && console.log(msg);
            cordova.fireWindowEvent("cordovacallbackerror", { 'message': msg });
            throw err;
        }
    },
...

exec.js exec代码片段

...
function androidExec(success, fail, service, action,args) {
    if (bridgeSecret < 0) {
        // If we ever catch this firing, we'll need to queue up exec()s
        // and fire them once we get a secret. For now, I don't think
        // it's possible for exec() to be called since plugins are parsed but
        // not run until until after onNativeReady.
        throw new Error('exec() called without bridgeSecret');
    }
    // Set default bridge modes if they have not already been set.
    // By default, we use the failsafe, since addJavascriptInterface breaks too often
    if (jsToNativeBridgeMode === undefined) {
        androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
    }

    // Process any ArrayBuffers in the args into a string.
    for (var i = 0; i < args.length; i++) {
        if (utils.typeName(args[i]) == 'ArrayBuffer') {
            args[i] = base64.fromArrayBuffer(args[i]);
        }
    }

    //
    var callbackId = service + cordova.callbackId++,
        argsJson = JSON.stringify(args);

    if (success || fail) {
        cordova.callbacks[callbackId] = {success:success, fail:fail};
    }

    var msgs = nativeApiProvider.get().exec(bridgeSecret, service, action, callbackId, argsJson);
    // If argsJson was received by Java as null, try again with the PROMPT bridge mode.
    // This happens in rare circumstances, such as when certain Unicode characters are passed over the bridge on a Galaxy S2.  See CB-2666.
    if (jsToNativeBridgeMode == jsToNativeModes.JS_OBJECT && msgs === "@Null arguments.") {
        androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT);
        androidExec(success, fail, service, action, args);
        androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
    } else if (msgs) {
        messagesFromNative.push(msgs);
        // Always process async to avoid exceptions messing up stack.
        nextTick(processMessages);
    } } 
    ... 
    

这篇关于javascript - Cordova重复执行异步方法,会覆盖前一个回调函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆