有没有大神能把cocos creator的http请求封装成wx.request那种格式啊?

因为以前往微信和抖音发布小游戏时,里面用了大量的wx.request这样的接口做http请求,现在需要往原生平台发布了,没法用wx.request接口了,但为了尽量少改动代码,所以想把cocos creator的http请求,就是getXMLHttpRequest这东西封装的尽量和wx.request的调用格式一样,就像下面这种调用方法
wx.request({
url: “myUrl”,
data: {
data1: “”,
data2: “”,
},
success: (res) => {
console.log(res);
},
fail: (res) => {
console.log(res);
},
complete: (res) => {
console.log(res);
},
})

从网上找了个cocos creator的http请求封装的代码,虽然用起来也没问题,但还是感觉没有wx.request这种格式调用起来方便,下面是网上找的代码

var httpUtils = cc.Class({
    extends: cc.Component,

    properties: {
    },

    statics: {
        instance: null
    },

    // use this for initialization
    onLoad: function () {
    },

    httpGets: function (url, callback) {
        var xhr = cc.loader.getXMLHttpRequest();
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 && (xhr.status >= 200 && xhr.status < 300)) {
                var respone = xhr.responseText;
                callback(respone);
            }
        };
        xhr.open("GET", url, true);
        if (cc.sys.isNative) {
            xhr.setRequestHeader("Accept-Encoding", "gzip,deflate");
        }

        // note: In Internet Explorer, the timeout property may be set only after calling the open()
        // method and before calling the send() method.
        xhr.timeout = 5000;// 5 seconds for timeout

        xhr.send();
    },

    httpPost: function (url, params, callback) {
        var xhr = cc.loader.getXMLHttpRequest();
        xhr.onreadystatechange = function () {
            cc.log('xhr.readyState=' + xhr.readyState + '  xhr.status=' + xhr.status);
            if (xhr.readyState === 4 && (xhr.status >= 200 && xhr.status < 300)) {
                var respone = xhr.responseText;
                callback(respone);
            } else {
                callback(-1);
            }
        };
        xhr.open("POST", url, true);
        if (cc.sys.isNative) {
            xhr.setRequestHeader("Accept-Encoding", "gzip,deflate");
        }

        // note: In Internet Explorer, the timeout property may be set only after calling the open()
        // method and before calling the send() method.
        xhr.timeout = 5000;// 5 seconds for timeout

        xhr.send(params);
    }
});

httpUtils.getInstance = function () {
    if (httpUtils.instance == null) {
        httpUtils.instance = new httpUtils();
    }
    return httpUtils.instance;
};

个人理解,肯定是把里面的httpPost方法稍微改动一下,重新封装个request方法(就是可以指定url和data参数,然后有回调的success、fail、complete)就可以了,但无奈本人javascript功力实在欠缺,自己封装不好,如果哪位老师有时间,能帮忙封装一下吗?或者用伪代码的方式指点一下也可以。我知道,这个httpPost方法直接用也算比较方便,也没问题,无奈就是还是不如和wx.request一模一样更方便。唉,最近脑子越来越不好使了,这问题显然是伸手党了。如果各位老师不嫌弃的话,请多多指教,万分感谢!

javascript实在不熟,颤颤巍巍地自己封装了一个可以替代wx.request的方法,用的是POST。感觉用GET和POST都无所谓,目的是为了从小游戏的代码改为发布到原生平台时,在http请求这块可以尽量地少改动代码而平滑过渡。

var httpUtils = cc.Class({
    extends: cc.Component,

    properties: {

    },

    statics: {
        instance: null
    },

    // use this for initialization
    onLoad: function () {
    },


    httpPostRequest: function (obj) {
        var url = obj.url;
        var data = obj.data;
        var success = obj.success;
        var fail = obj.fail;
        var complete = obj.complete;

        var dataStr = '';
        Object.keys(data).forEach(key => {
            dataStr += key + '=' + encodeURIComponent(data[key]) + '&';
        })
        if (dataStr !== '') {
            dataStr = dataStr.substr(0, dataStr.lastIndexOf('&'));
        }


        console.log("dataStr", dataStr)

        var xhr = cc.loader.getXMLHttpRequest();
        xhr.onreadystatechange = function () {
            cc.log('xhr.readyState=' + xhr.readyState + '  xhr.status=' + xhr.status);
            if (xhr.readyState === 4 && (xhr.status >= 200 && xhr.status < 300)) {
                var res = new Object();
                res.statusCode = xhr.status;
                res.data = JSON.parse(xhr.responseText);         
                if (typeof success == "function") {
                    success(res);
                }
            } else {
                if (typeof fail == "function") {
                    fail(-1);
                }
            }
            if (typeof complete == "function") {
                complete(0);
            }
        };
        xhr.open("POST", url, true);


        if (cc.sys.isNative){
            xhr.setRequestHeader("Accept-Encoding", "gzip,deflate");
        }
        xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); 

        // note: In Internet Explorer, the timeout property may be set only after calling the open()
        // method and before calling the send() method.
        xhr.timeout = 5000;// 5 seconds for timeout

        // xhr.send('"platformFlag":4,"programID":12,"catalog":"main VERSION:1.0.0","position":"onStartGameClick11111111111111"');
        xhr.send(dataStr)
    },


});

httpUtils.getInstance = function () {
    if (httpUtils.instance == null) {
        httpUtils.instance = new httpUtils();
    }
    return httpUtils.instance;
};

上述代码命名为httpUtils.js就可以了,然后在cocos creator里面导入为插件,就可以在任何地方都直接调用了。从小游戏代码改为原生代码时,只需要把wx.request替代为httpUtils.getInstance().httpPostRequest就可以在原生平台使用了(就是只替换函数名),其他地方不用做任何改变(除非你的参数特别多,如果那样,你自己在httpPostRequest里面稍微扩展一下就可以了)。我特意封装这么一个方法,其实主要是适用于在小游戏里面大量使用了wx.request的代码,这样,基本可以平滑的从小游戏切换到原生了。不然,大量修改wx.request调用的地方,即麻烦也容易出错。

我把cocos的http请求,利用zipto进行了封装,看看是否对你有用。
cocos creator 2.4可用,3.0后没有测试。
zipto是jquery的精简版,$.ajax({…})是基本用法。
使用示例:

const $ = require('zepto');
function appendQuery(url, query) {
    if (query == '') return url
    return (url + '&' + query).replace(/[&?]{1,2}/, '?')
}

function getOptions(url, data, success) {
    if ($.isFunction(data))  success = data, data = undefined
    return {
        url: url
        , data: data
        , success: success
        , dataType: 'json'
    }
}

function get(/* url, data, success */) {
    return $.ajax(getOptions.apply(null, arguments)).then((res)=>{
        if(res.code==='0'){
            return res.data;
        }
    })
}

function post(/* url, data, success */) {
    let options = getOptions.apply(null, arguments)
    options.type = 'POST';
    options.contentType = 'application/json';
    options.data = JSON.stringify({"data":options.data})
    return $.ajax(options).then((res)=>{
        if(res.code==='0'){
            return res.data;
        }
    })
}

module.exports = {
    get:get,
    post:post
};

zepto.zip (8.4 KB)

感谢回复,我看您post里面contentType = ‘application/json’。我现在就好奇,为什么wx.request要求post的contentType必须 是application/x-www-form-urlencoded

基本概念,自行百度他们之间的区别吧。

感谢回复,get和post的区别我大概是明白的,现在不太明白的是wx.request要求post的contentType必须 是application/x-www-form-urlencoded(规定死了,只能是application/x-www-form-urlencoded,不能是其他),但网上其他的很多地方(或者比如您),post就是contentType = ‘application/json’

现在应该是搞明白了,所谓网上说的wx.request要求post的contentType必须 是application/x-www-form-urlencoded,是因为wx.request默认contentType = ‘application/json’,但很多人的服务器端用的是request.getParameter,这就导致他们服务器端读取不到数据。于是他们改成contentType = ‘application/x-www-form-urlencoded’就可以了。所以他们以为必须设置为contentType = ‘application/x-www-form-urlencoded’。

其实,说到底,还是他们的前端和后端没设置一致导致的,而并非wx.request规定必须是contentType = ‘application/x-www-form-urlencoded’。

也是我自己的概念不清,看了网上的文章就糊涂了。

1赞