Ts手动封装http请求

发布时间:2023年12月31日

博主在进行Cocos小游戏的开始时,想要实现http请求。简单的用node.js在本地搭了一个服务器后,查询Cocos的官方文档以及网上搜索,都没有发现官方封装的API。

博主之前从事原生微信小程序开发以及uniapp开发,使用惯了方便快捷的requestAPI,以为这个是很简单的一个东西。结果Cocos官方并没有封装过http请求!也是走了很多弯路,手动封装了一下http请求(每次都使用原生Js写法真的很让人抓狂),这里写出代码和具体思路,供诸位参考。

一、Js原生http请求的实现介绍

首先,Js原生http请求是使用XMLHttpRequest实现的。虽然这个东东以XML为前缀,但是其实也可以进行JSON格式数据的传输。

const xhr = new XMLHttpRequest();//创建XMLHttpRequest示例对象
xhr.setRequestHeader('Content-Type','application/json');//设置请求头,用来适配json格式数据传输
xhr.open('POST',url,true);//初始化请求,设置请求方式,请求地址,是否异步调用
xhr.send(JSON.stringfy(params));//发送请求参数(请求参数是跟在url后面的一串字符串,如?name=张三&age=18)

值得注意的是,参数其实是不支持中文字符的,但是为什么我们传入name=张三也是合法的呢?原因是绝大多数浏览器会自动将中文字符进行转码,弄成%开头的一堆数字。原本我们也是需要在脚本里面使用encodeURI这个函数进行转码的,但是这活被浏览器干了,倒也省心。

这四行代码就可以实现简单的请求了。但是我们还没有拿到请求数据。

xhr内置四个监听函数

xhr.onerror = ()=>{//处理错误逻辑}
xhr.onprogress = ()=>{//处理加载逻辑}
xhr.onloadend = ()=>{//处理请求结束逻辑}
xhr.ontimeout = ()=>{//处理超时逻辑}

除此之外,还有一个可以监听到所有事件的函数

xhr.onreadystatechange = ()=>{//在这里处理所有事件逻辑}

一般来说,我们使用xhr.onreadystatechange就够了。

xhr.onreadystatechange = ()=>{
    if(xhr.readyState === 4 && (xhr.status >= 200 && xhr.status < 300)){
        console.log(xhr.responseText)
    }
}

readyState有几个可取值,分别代表不同状态,4就是加载完成的状态。status是请求的状态码,通常200为请求成功。之后在responseText中获得返回的数据,如果是JSON格式数据,还可以再调用JSON.parse来转成js对象。

二、封装请求实现思路

首先我们应该清楚为什么要实现封装。因为现有的请求太过于繁琐,需要在不同的地方设置很多参数。而事实上我们需要的是什么,我们只需要上传信息,然后拿到信息就可以了。而且,如果想要区别请求的状态,就需要利用到xhr的四个监听函数用来细分。与此同时,我们还需要建立错误反馈机制,用来方便之后调试。所以我们的思路是,进一步的封装应该要在利用xhr的多个监听函数的基础上,并且能够实现一次传参直接获得消息。

这方面也不能忽略的是,网络请求是需要较长的响应时间的。如果在网络条件比较差或者传输数据量比较大的情况下,使用同步请求会阻塞主线程,导致之后的程序无法运行。所以应该设计成异步函数。

export class Http {
    public static get(url, callback, thisObj) {
        var xhr = new XMLHttpRequest();
     
        xhr.onerror = function () {
            callback.call(thisObj, "ERROR", xhr)
        }

        xhr.onprogress = function () {
            callback.call(thisObj, "PROGRESS", xhr)
        }

        xhr.onloadend = function () {
            callback.call(thisObj, "COMPLETE", xhr)
        }

        xhr.ontimeout = function () {
            callback.call(thisObj, "TIMEOUT", xhr)
        }
        xhr.open("GET", url, true);//这里的true意思是允许异步请求
        xhr.setRequestHeader('Content-Type', 'application/json');

        xhr.send();//这里不写参数的原因是,参数也可以直接放在url里,我们在进一步封装之后,直接写到url中
    }
}
    

首先进行简单封装,设置请求方式和数据格式。这个模块只能实现最简单的请求功能。

?httpSend(subUrl, params, callback) {
        var param = this.obj_contact(params);
        var url = this.baseUrl + '/' + subUrl + param;
        Http.get(url, function (eventName: string, xhr: XMLHttpRequest) {
            if (eventName == 'COMPLETE') {
                if (xhr.readyState == 4 && (xhr.status >= 200 && xhr.status < 400)) {
                    var response = JSON.parse(xhr.responseText)
                    callback && callback(response);
                } else {
                    console.log('服务器维护中');
                }
            } else if (eventName == 'TIMEOUT') {
                console.log("连接网关超时")
            } else if (eventName == 'ERROR') {
                console.log("连接网关发生错误")
            }
        }, this);
    }

?

?

接着进行第二步封装,这步封装中我们利用了回调函数。第一步封装我们传入回调函数两个参数,分别为请求状态字符串和xhr实例对象。返回的数据储存在xhr实例对象内,所以必须传入,而请求状态字符串可以提示当前的请求状态,也需要传入。这里说明一下baseUrl就是所请求网站的域名,subUrl就是该网站域名下的文件路径。然后通过自己写的一个函数obj_contact来将js对象转化为?key1=value1&key2=value2...的格式,加到完整域名的后面。

这里写出obj_contact的具体实现

  public obj_contact(obj) {
        var s = "";
        for (var k in obj) {
            let v = obj[k];
            if (s.length == 0) {
                s += "?" + k + "=" + v;
            } else {
                s += "&" + k + "=" + v;
            }
        }
        return s;
    }

一个很简单的函数。

写到这里,我们发现还没有拿到服务器返回的消息。其实可以两步解决的,在第一步封装的回调函数里我们就可以把xhr.responseText当做参数返回的。但是我们的函数体会显得很臃肿,因为第二步封装里的函数还需要执行请求状态的判断,所以我们进行第三步封装。

var params = {"name":"张三","id":"01","age":"18"};
var subUrl = "test/demo";
httpGet(subUrl, params, (res) => {
           if (res.code == 200) {
               if (res.data) {
                   this.data = res.data
               }
           })

?

?

现在我们的函数看上去就很简洁了,只需要传入两个信息就能得到数据了,同样,Post请求也可以这样封装。

文章来源:https://blog.csdn.net/2301_80005044/article/details/135317599
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。