跳转至

网络请求XMLHttpRequest的扩展

这个类包含了http的get和post请求以及数据返回后的处理,采用的是callback的形式,当然也可以转换为使用promise来做,如有需要请自行修改

export class HttpRequest
{
    private static _inst:HttpRequest;

    private constructor()
    {
    }
    /** 获取单例*/
    static getInst():HttpRequest
    {
        if(!this._inst)
        {
            this._inst = new HttpRequest();
        }
        return this._inst;
    }

    /** get请求*/
    doGet(url:string, headers, params, cb:handler)
    {
        if(params)
        {
            if(url.indexOf("?") == -1)
            {
                url += "?";
            }
            url += this.getQueryString(params);
        }
        this.doHttp(url, headers, null, "GET", cb);
    }

    /** post 请求*/
    doPost(url:string, headers, params, cb:handler)
    {
        this.doHttp(url, headers, params, "POST", cb);
    }

    /** 最终完整的请求*/
    private doHttp(url:string, headers, params, method:string, cb:handler)
    {
        const xhr = new XMLHttpRequest();
        xhr.responseType = "text";
        xhr.onreadystatechange = this.onReadyStateChange.bind(this, xhr, cb);
        xhr.ontimeout = this.onTimeout.bind(this, xhr, url);
        xhr.onerror = this.onError.bind(this, xhr, url);
        xhr.onabort = this.onAbort.bind(this, xhr, url);

        cc.log(`HttpRequest, doHttp url=${url}, method=${method}, parmas=${params}`)
        xhr.open(method, url, true);
        if(headers)
        {
            this.setHttpHeaders(xhr, headers);
        }
        if (cc.sys.isNative)
        {
            this.setHttpHeaders(xhr, {"Accept-Encoding": "gzip,deflate"});
        }
        if(params && typeof params === "object")
        {
            params = JSON.stringify(params);
        }
        xhr.send(params);
    }

    /** 正常返回的处理*/
    private onReadyStateChange(xhr:XMLHttpRequest, cb:handler)
    {
        cc.log(`HttpRequest, onReadyStateChange, readyState=${xhr.readyState}, status=${xhr.status}`);
        if(xhr.readyState === 4 && xhr.status >= 200 && xhr.status < 300) 
        {
            cc.log(`HttpRequest, onReadyStateChange, responseText=${xhr.responseText}`);
            let data;
            let code = HttpCode.kUnknown;
            const response = JSON.parse(xhr.responseText);
            if(response && response.code)
            {
                code = response.code;
                data = response.content; 
            }
            else
            {
                code = HttpCode.kSuccess;
                data = response;
            }
            this.notifyCallback(cb, code, data);
            this.removeXhrEvent(xhr);
        }
    }

    /** 超时的处理*/
    private onTimeout(xhr:XMLHttpRequest, url:string)
    {
        cc.warn(`${url}, request ontimeout`);
        this.removeXhrEvent(xhr);
    }

    /** 错误的处理*/
    private onError(xhr:XMLHttpRequest, url:string)
    {
        cc.warn(`${url}, request onerror`);
        this.removeXhrEvent(xhr);
    }

    /** 中断的处理*/
    private onAbort(xhr:XMLHttpRequest, url:string)
    {
        cc.warn(`${url}, request onabort`);
        this.removeXhrEvent(xhr);
    }

    /** 移除监听事件*/
    private removeXhrEvent(xhr:XMLHttpRequest)
    {
        xhr.ontimeout = null;
        xhr.onerror = null;
        xhr.onabort = null;
        xhr.onreadystatechange = null;
    }

    /** 返回数据*/
    private notifyCallback(cb:handler, code:number, data?)
    {
        if(cb)
        {
            cb.exec(code, data);
        }
    }

    /** 设置http请求的头部*/
    private setHttpHeaders(xhr:XMLHttpRequest, headers)
    {
        for(let key in headers)
        {
            xhr.setRequestHeader(key, headers[key]);
        }
    }

    /** 拼接请求的参数*/
    private getQueryString(params)
    {
        const tmps:string[] = [];
        for(let key in params)
        {
            tmps.push(`${key}=${params[key]}`);
        }
        return tmps.join("&");
    }
}

/** 状态码*/
export enum HttpCode {
    kSuccess = 0,
    kTimeout = 10000,
    kUnknown = 10001,
    kSessionTimeout = -8,
    kIAmInBlocklist = -3013,
    kUserIsInMyBlocklist = -3014
}

/**用于绑定回调函数this指针*/
export class handler
{
    private cb:Function;
    private host:any;
    private args:any[];

    constructor(){}

    init(cb:Function, host = null, ...args)
    {
        this.cb = cb;
        this.host = host;
        this.args = args;
    }

    exec(...extras)
    {
        this.cb.apply(this.host, this.args.concat(extras));
    }
}

友情链接