Android下XMLHttpRequest出错

问题描述

在Android包下,使用了第三方SDK登录,在切出去登录成功后,在SDK的回调中使用runOnGLThread线程回调到TS代码中。

appActivity.runOnGLThread(new Runnable() {
                        @Override
                        public void run() {
                            Cocos2dxJavascriptJavaBridge.evalString("SystemBridge.OnLoginSuccess(\""+ accessToken + "\",\"" + userId+"\")");
                        }
                    });

然后,在TS代码中,使用了XMLHttpRequest的post协议异步请求消息向服务器登录。

public static OnLoginSuccess(token: string, id: string) {
        let postData = {
            "token":token,
            "id":id
        }
        var xhr = new XMLHttpRequest();
        xhr.responseType = 'arraybuffer';
        xhr.onreadystatechange = () => {
            if (xhr.readyState === 4) {
                if (xhr.status >= 200 && xhr.status < 300) {
                    // TODO 处理登录成功
                }
            }
        };
        xhr.open("POST", "登录服务器Url", true);
        xhr.timeout = 10000;
        xhr.ontimeout = () => {
                    // TODO 处理登录超时
        }
        xhr.send(postData);
        xhr.onerror = () => {
                    // TODO 处理登录错误
        }
}

最后返回的结果是 刚发送数据同一帧就收到了ontimeout的回调,然后部分手机还会出现崩溃情况。

分析

XMLHttpRequest 的异步逻辑类似于setTimeout,setTimeout 和 XMLHttpRequest.onreadystatechange 用的都是同一个 Event Queue,唯一区别是 setTimeout 是定时器线程往队列里压,XMLHttpRequest.onreadystatechange 是 HTTP 异步请求线程往队列里压,其逻辑就要看CocosCreator的Main Loop了。可能原因是应用从别的程序中切换过来时,导致Main Loop回调出了点问题。

解决办法

就是在整个post时,用schedule做一个延迟回调。等到Event Queue队列循环正常后再调用post函数就可以了。

    public static OnLoginSuccess(token: string, id: string) {
        Timer.scheduleOnce(() => {
            let postData = {
            "token":token,
            "id":id
        }
        ...
        其他代码 
        }, 0.1)
    }
0%