这次给大家带来JS中使用接口步骤详解,JS中使用接口的注意事项有哪些,下面就是实战案例,一起来看一下。
这篇是 js-interface 的 README,虽然并不是很复杂的一个东西,如果有人看的话我就写写源码思路了 ORZ
介绍
在做一个前后分离的项目时,有些头疼 Api 之类的东西要怎么管理,在阅读 《JavaScript 设计模式》 一书时,第二章提到了在 JavaScript 中模拟接口 (interface) 的概念,以方便使用众多设计模式,因此尝试着做一个接口的模拟。由于我本职是一名后端 Java 开发,因此希望在这个模拟层可以加入 接口默认实现、接口继承、方法重载 等能力,虽然这些东西加上之后不可避免得会在性能上有所牺牲,但对我来说可以提升一些开发体验(我知道 TypeScript,只是想搞个轮子试试 :P)。
使用
既然初衷是为了方便管理 Api,那么就做一个关于 Api 的 demo。
创建一个接口
const config = { // 接口的名字 name: 'IApi', // 是否打开此接口的 debug 开关 // 开发时必须打开,否则不会启动 (方法声明、方法实现等)入参的类型检查。 // 打开这个的情况下,还会获得一些调试用的信息。 debug: true, } let IApi = new Interface(config)
声明方法
最简单的声明方式:
IApi.method({name: 'getName'}) // 等价于 IApi.method({name: 'getName', args: undefined})
这样就声明了 IApi
接口含有一个 getName
方法,它没有任何参数,也没有默认实现,这就要求在后面任何 IApi
的子接口或实现类必须实现该方法,否则会抛出一个异常。
如果想指定方法的参数列表:
IApi.method({ name: 'getName', args: null })
注意!
args
为 null
时表示该方法可以接受任意数量的任意参数,如果重载了一个方法(详细的请参阅后面关于重载的说明):
// 声明一个空参方法 IApi.method({ id: 0, name: 'getName', args: null }) // 重载上面的方法,使其有且只有一个 'string' 类型,名为 name 的参数 IApi.method({ id: 1, name: 'getName', args: [ {name: 'name', type: 'string', support: val => typeof val === 'string'} ] })
注意!
在参数描述中,type
属性只是一个字符串值,它并不真的代表参数的实际类型。它跟 name
属性一样只是提供用于调试的信息,因此你可以填入任何你认为合适的、足以标记该参数一些信息的字符串值。
真正决定方法是否接受该参数的是 support
属性,当它返回 true
时会检查下一个参数直到所有参数检查完毕或某个位置的参数不被接受。
如果需要,可以在 support
中对实际入参进行特殊处理,比如转换对象、特定属性检查等等。
如果想为方法提供默认实现:
IApi.method({ name: 'getName', // 默认实现,不能为箭头函数! implement: function() { return "IApi" } })
回到我们的 demo,综合运用一下:
// 声明两个方法,它们都没有参数,也不需要重载因此这样就可以了 IApi .method({ name: 'getName' }) // 项目中使用 Axios,因此这里需要一个方法来获取 axios 实例 .method({ name: 'getAxios' }) // 声明四个请求方式对应的方法 const methods = ['get', 'post', 'put', 'delete'] methods.forEach(method => { IApi.method({ name: method, args: null, implement: function() { // 处理了 this 指向问题,放心用吧 return this.getAxios()[method].apply(this, arguments) .then(responseHandler) .catch(errorHandler) } }) })
继承接口
假定我们要创建接口 A,要继承 B、C、D、E 等接口,使用如下语句:
const A = new Interface({ name: 'A', debug: true }).extends([B, C, D, E])
extends
方法会将传入的接口所持有的所有方法声明(即通过 Interface.method(config)
所声明的那些方法 )拷贝至接口 A,包括那些方法声明的默认实现。
注意!
一般来说,不会在多个接口中重载同一个方法签名,但如果真的有这样的需求,可以自行设置 id
的规则,比如:
const B = new Interface(...) .method({ id: 'B00', name: 'getName', args = [...] }) .method({ id: 'B01', name: 'getName', args = [...] }) const C = new Interface(...) .method({ id: 'C00', name: 'getName', args = [...] })
然后实现该方法时指定要实现哪一个声明:
// 注意!如果一个方法被重载,则不能在 class 中声明该方法。 class AImpl { ... } const AInstance = new AImpl(...) B.implement({ object: AInstance, id: 'B00', // 指定要实现的方法声明 name: 'getName' })
再次回到我们的 demo,综合运用一下:
const IAuthenticationApi = new Interface({ name: 'IAuthentication', debug: true }) // 指明 IAuthenticationApi 继承自 IApi 接口 .extends(IApi) IAuthenticationApi // 重载方法 login // loin (username :string, password :string) .method({ id: 0, name: 'login', args: [ {name: 'username', type: 'string', support: val => typeof val === 'string'}, {name: 'password', type: 'string', support: val => typeof val === 'string'} ] }) // login() .method({ id: 1, name: 'login' })
实现接口
// 编写一个实现类 class AuthenticationApi { constructor(axios) { this.axios = axios } // 直接实现 getName 方法 getName() { return "AuthenticationApi" } // 直接实现 getAxios 方法 getAxios() { return this.axios } } // 实现重载方法 IAuthenticationApi .implement({ // 指定挂载实现到 AuthenticationApi 上 object: AuthenticationApi, // 指定此实现是对应 id 为 0 的方法声明 id: 0, name: 'login', implement: function(username, password) { console.log('带参数的 login') // 还记得我们在 IApi 接口中定义了 get 方法(包括默认实现)吗? this.get('https://www.baidu.com') return Promise.resolve('hello') } }) .implement({ object: AuthenticationApi, id: 1, name: 'login', implement: function () { console.log('无参数的 login') }, }) IAuthenticationApi.ensureImplements(AuthenticationApi)
使用接口实现类
let authenticationService = new AuthenticationApi(axios) // 挂载代理函数到实例上,否则会提示 // Uncaught TypeError: authenticationService.login is not a function IAuthenticationApi.ensureImplements(authenticationService) authenticationService .login('sitdownload', '1498696873') // login(string, string) 会返回一个 Promise 还记得吗 :P .then(str => alert(`${str} world!`)) authenticationService.login()
关于日志
首先确保在创建接口时打开了 debug 开关({ debug: true }
)。
上面的 demo 运行正常的话你将会得到下面的日志:
// 注册方法 Interface 注册方法: IApi.getName() Interface 注册方法: IApi.getAxios() Interface 注册方法: IApi.get(any) Interface 注册方法: IApi.post(any) Interface 注册方法: IApi.put(any) Interface 注册方法: IApi.delete(any) Interface 注册方法: IAuthentication extends IApi.getName() Interface 注册方法: IAuthentication extends IApi.getAxios() Interface 注册方法: IAuthentication extends IApi.get(any) Interface 注册方法: IAuthentication extends IApi.post(any) Interface 注册方法: IAuthentication extends IApi.put(any) Interface 注册方法: IAuthentication extends IApi.delete(any) Interface 注册方法: [0]IAuthentication.login(username :string, password :string) Interface 注册方法: [1]IAuthentication.login() // 实现方法 Interface 实现方法: 保存 [0]IAuthentication.login(...) 实现: ƒ implement(username, password) Interface 实现方法: 保存 [1]IAuthentication.login(...) 实现: ƒ implement() // 匹配方法 Interface 方法匹配: 精准匹配 IAuthentication.login({ username: "sitdownload" } :string, { password: "1498696873" } :string). // 在控制台这行是可以打开实现的具体位置的 ƒ implement(username, password) // 方法输出 AuthenticationApi.js?7b55:25 带参数的 login // 匹配方法 Interface 方法匹配: 无法精准匹配 IAuthentication.get("https://www.baidu.com"),使用 any 实现匹配: ƒ implement() Interface 方法匹配: 精准匹配 IAuthentication.login(). ƒ implement() // 方法输出 AuthenticationApi.js?7b55:35 无参数的 login // AuthenticationApi.login(username, password) 中请求了 'https://www.baidu.com' Failed to load https://www.baidu.com/: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1' is therefore not allowed access. // IApi.get(any) 中将异常直接向下抛了 Uncaught (in promise) {type: "network", payload: Error: Network Error at createError (webpack-internal:///./node_modules/_axios@0.18.0@axios/lib/…}
后续
如果要发版了,确认所有的接口方法都正确实现后,就可以把 debug 关掉,这样就不会有 Interface
内部的一些入参检查和调试输出。
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
以上是JS中使用接口步骤详解的详细内容。更多信息请关注PHP中文网其他相关文章!

Node.js擅长于高效I/O,这在很大程度上要归功于流。 流媒体汇总处理数据,避免内存过载 - 大型文件,网络任务和实时应用程序的理想。将流与打字稿的类型安全结合起来创建POWE

Python和JavaScript在性能和效率方面的差异主要体现在:1)Python作为解释型语言,运行速度较慢,但开发效率高,适合快速原型开发;2)JavaScript在浏览器中受限于单线程,但在Node.js中可利用多线程和异步I/O提升性能,两者在实际项目中各有优势。

JavaScript起源于1995年,由布兰登·艾克创造,实现语言为C语言。1.C语言为JavaScript提供了高性能和系统级编程能力。2.JavaScript的内存管理和性能优化依赖于C语言。3.C语言的跨平台特性帮助JavaScript在不同操作系统上高效运行。

JavaScript在浏览器和Node.js环境中运行,依赖JavaScript引擎解析和执行代码。1)解析阶段生成抽象语法树(AST);2)编译阶段将AST转换为字节码或机器码;3)执行阶段执行编译后的代码。

Python和JavaScript的未来趋势包括:1.Python将巩固在科学计算和AI领域的地位,2.JavaScript将推动Web技术发展,3.跨平台开发将成为热门,4.性能优化将是重点。两者都将继续在各自领域扩展应用场景,并在性能上有更多突破。

Python和JavaScript在开发环境上的选择都很重要。1)Python的开发环境包括PyCharm、JupyterNotebook和Anaconda,适合数据科学和快速原型开发。2)JavaScript的开发环境包括Node.js、VSCode和Webpack,适用于前端和后端开发。根据项目需求选择合适的工具可以提高开发效率和项目成功率。

是的,JavaScript的引擎核心是用C语言编写的。1)C语言提供了高效性能和底层控制,适合JavaScript引擎的开发。2)以V8引擎为例,其核心用C 编写,结合了C的效率和面向对象特性。3)JavaScript引擎的工作原理包括解析、编译和执行,C语言在这些过程中发挥关键作用。

JavaScript是现代网站的核心,因为它增强了网页的交互性和动态性。1)它允许在不刷新页面的情况下改变内容,2)通过DOMAPI操作网页,3)支持复杂的交互效果如动画和拖放,4)优化性能和最佳实践提高用户体验。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

DVWA
Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

禅工作室 13.0.1
功能强大的PHP集成开发环境

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境