持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情
背景
业务急需一个oss直传公共包进行开发,并给出了以下设计要求
但调研过ali-oss后,我发现他基本功能都实现了,没必要再过度去封装,设计上要求的方法其实都有的了,就是方法名不一样,然后参数也是需要调整。所以反馈到组长希望更改设计
设计
使用直传之前需要获取STS临时访问凭证。也就是意味着我们需要3步操作才能使用上oss的真正功能:获取sts->实例化oss->调用oss能力。
// ali-oss的基本使用
import OSS from 'ali-oss'
import fetchSTS from './api'
fetchSTS(token)
.then(res => {
const client = new OSS({
...res,
...params
})
return client.put('test/ab.jpeg', file)
})
.then(伪代码)
我们能否把获取sts这步内部消化掉呢?就这是我接下来要做的一件事,把上面说的3步变成 闭包函数->调用oss能力
// 封装后的oss
export { createImageOSS } from 'oss'
// token用来换sts
const oss = createImageOSS(token)
// dir, fileName, file
oss.put('test/', 'ab.jpeg', file).then(伪代码)
内部消化
获取sts是通过调后端接口获取,也就是内部需要有一个能力,可以等待异步结束,那这个非Promise莫属,我们只需要在oss调用方法的时候,返回一个new Promise,在里面获取sts、进行实例化、最后调用对应的方法,同时在实例化后,把该对象保留到内部变量里面,形成一个闭包,下次再调用方法,判断已经实例化就直接走方法调用即可
代理妙用
oss是没有dir这个参数的,我这边需要对所有特定方法进行参数拦截,这时候proxy英雄登场,通过拦截方法进行懒包装。当然,判断环境不支持的话,自动降级到Object.defineProperty,只是不懒罢了
通过proxy对内部oss实例进行了代理,判断是否特定方法,是的话修改其入参行为,需求上返回数据也需要做扩展,这是为了使用部门内部的cdn图片地址,我需要拦截返回行为,对其返回数据进行加工。为了后续更好的扩展,从其中解耦出拦截对象,可以隔离开内部逻辑进行定制
// 拦截对象
{
then, // 拦截返回数据逻辑
params, // 拦截入参逻辑
}
重写ts声明文件
因为ali-oss的ts声明文件的入参并没有dir,返回也没有cdnUrl这些字段,我是直接拷贝其声明文件进行维护,还发现了声明文件的bug,随手给DefinitelyTyped来个pr
谢幕
上述设计主要做了两件事
- sts获取屏蔽
- 入参与返回拦截 功能调用跟ali-oss一模一样,所以api可直接参考ali-oss 文档使用
对外看起来非常自然,连文档都省了,自然到好像什么都没做,又好像什么都做了。这大概就是萧规曹随吧