当前位置: 首页 > Web前端 > JavaScript

B端web项目处理不同交付之间的接口差异,《工程》

时间:2023-03-27 00:25:29 JavaScript

逻辑构思最近,京东在开发自己的IDE时,遇到了一个有趣的问题。由于项目是IOT特有的,有些接口是为不同方定制的,不同方需要的功能自然不同,提供的接口(如加密签名、token签名)自然也不同。之前的方式==“请求根包+接口列表”==很难满足其灵活多变的需求,在并行处理单个项目的多次交付时也是捉襟见肘。因此针对此类问题重新设计了一种网络请求的黑盒封装方式。它可以在任何环境下使用,无论是vue、react还是node。.首先我们确认一下要实现的目标:整个项目的网络部分要变成可配置的,甲方对应一个配置文件,配置文件必须能够直接配置或者处理不同的定制服务,比如baseURL和headers等。此外,它应该能够支持对旧项目的向后兼容,并保留原有的通用接口封装方式,保持可读性,几乎不需要学习成本。常用的接口封装方法如下,});returnres;}文件结构设计的文件结构大致如下src-|...|-config|-serve.ts(服务核心)|-serve|-a.ts(甲方)|-b.ts(乙方)|...|...按照这样的设计,如果后面有新的一方需要投递,只需要在config/serve文件夹下新增一个文件即可,不会影响其他的投递,也方便统一配置.为核心封装服务为了更容易介绍代码逻辑和涉及到的众多知识点,我将在本章详细说明如何进行封装。当然,你可以边看本章边看下一章的UML图,辅助理解(解释在代码下方)serve.tsimportrequestfrom'../xxxxxxx/request';//这里是项目的请求根路径//默认值,这里也可以自定义项目的一些公共配置constdefaultConfig=除了平台{platform:'default',configuration:'independent'//independent独立配置,overall整体配置}/**这两个接口其实应该写在外面,文章写在这里方便查看*/interfacemagicType{//这里需要写的很详细_base_url:{release:string,dev:string,test:string,},_header:{sign:Function,//...}}interfaceencType{平台:字符串,配置:字符串}classServeCore{平台:字符串;//平台识别请求:any;//魔法修改请求root[prop:string]:any;构造函数(ENC:encType=defaultConfig){this.platform=ENC.platform;(async()=>{constexport_list=awaitimport(`./serve/${this.platform}`);//[nameisconfig]整体配置ENC.configuration==='overall'&&(this.request=this.magicRequest(export_list['config']));for(let__function__inexport_list){//魔改配置应该有两条判断规则?(byname,bytype)if(typeofexport_list[__function__]==='function'||__function__!=='config'){//这里是需要注册到租用设备的接口函数,[is函数类型||thenameisnotconfig]this[__function__]=export_list[__function__].bind({request:this.request})}else{//【既不是函数类型,name也叫config】独立配置ENC.configuration==='独立'&&(this.request=this.magicRequest(export_list[__function__]));}}console.log('===========这个',这个);删除这个。然后;返回这个})();}//魔法请求方法magicRequest(config:magicType){//这里的做法是将配置绑定到请求的全局returnrequest.bind({config})}}export{ServeCore,//这里是用来重新自定义配置的magicType,encType}exportdefaultnewServeCore首先我们定义一个类,名字叫ServeCore,其中platform是平台标识(甲方),用来区分不同的平台;request是处理后打包的请求根,其实可以随时更改。后面的扩展会讲到按需加载文件。在构造函数中,我们需要根据需要动态更改目标甲方平台对应的文件。把它引入到这个calss中进行处理,可惜js中类构造函数的目的是返回构造好的实例,不支持等待异步操作(因为那样的话返回的会是一个promise对象,而一个error这里会在运行时报错),不过好在我们知道js类只是一个函数的语法糖,底层还是函数实现,所以我在构造函数中写了这样一个结构:constructor(ENC:encType=defaultConfig){(async()=>{//...deletethis.then;returnthis})();}目的是立即执行一个异步箭头函数作为返回值,实际上返回一个Promiseinstance,当Promiseresolved时会创建对象实例(this)返回,所以我们外部的await是在完成异步构造后拿到实例的。巧妙的绕过构造函数的机制,然后awaitimport导入不同方对应的文件进行处理,下面是一个demoa.ts的例子(甲方)//配置是不是应该先放?exportconstconfig={//TODO:目前需要讨论,但个人认为配置项应该作为直接字面量使用,而不是函数_base_url:{release:'https://xxx.com',dev:'https://xxx.com',test:'https://xxx.com',},_header:{sign:(param)=>{//这里实际的调用环境在请求中,所以最好使用一个函数?//...}}}//这是一个简单的demoexport异步函数getTest(params){constres=awaitrequest({url:'/getInfo/test',method:'POST',data:params,});returnres;}//...==先上班,等会儿回来补,还有很多没写清楚==xxx.tsximportServicefrom'../../config/serve'//...//在某个函数中:constres=awaitService.getTest(param);console.log(res)//这里ide会报错但实际上可以正常运行(有兴趣的可以画个思维导图)UML图如下:sequenceDiagram接口文件(a.js)->>+ServeCore:config(配置)和接口方法ServeCore->>+request(封装请求根):config(配置)request(封装请求根)->>+接口文件(a.js):magicmodifiedrequest接口文件(a.js)->>+ServeCore:bind魔改请求后的接口方法ServeCore->>+xxx.tsx(通用页面调用):网络接口方法请求权(封装请求根):完成处理界面相关链接参考:https://www.blackglory.me/asy...