们目前项目中的代码专门针对程序的边界做了一层封装,尤其是调用第三方应用的请求相关的代码。但是我感觉不是特别的好,且看下面这一段伪代码
- 类的定义
const axios = require('axios');
class Client {
constructor({ url, username, password }) {
this.url = url;
this.username = username;
this.password = password;
this.token = '';
this.login = this.login.bind(this);
this.getSomething = this.getSomething.bind(this);
this.login();
}
async login() {
const { token } = await axios.post(...);
this.token = token;
}
async getSomething(params) {
if (!this.token) {
console.error('未登录');
return;
}
const result = await axios.get(..., {
headers: {
token: this.token,
},
...
});
return result;
}
}
- 调用
const Client = require('./Client.js');
async main() {
const client = new Client({
url: '127.0.0.1',
username: 'zhangsan',
password: '...'
});
const result = await client.getSomething();
console.log(result);
}
他这里在实例化该对象是,构造函数调用了一个async
的函数,如果立即调用getSomething()
方法,可能会存在login()
方法还未执行完,token
还没有的情况。
请问一下大家一般是怎样封装这样的类的?或者说怎样处理这样的情况?
这个类似Node.js里调socket.connect返回一个socket,然后立刻调write一样,这时候可能还没有建立连接,处理就是getsomething的时候判断是否在获取token,不是的话直接请求,不然就把请求放到队列里或者基于事件订阅也行,token获取成功后,执行等待队列的请求或者触发事件。
讲设计应该先从调用代码开始
调用代码的意图看起来是想对外隐藏login这一层逻辑, 以减少调用方的复杂度
目前的实现, 一定运气上解决了这个问题, 运气是看什么时候调用 getSomething()
修正办法: 存储login 返回的promise, 让 getSomething() 检查这个 promise
class Client{
constructor(){
this.pmsLogin = this.login()
}
async getSomething(){
await this.pmsLogin
if(!this.token) {
// 此处应有重试, 超时策略等
}
}
}
@theanarkh 目前我能想到的方案也和你的一致,不过总感觉这样的客户端封装不如直接函数式编程了,反而有点增加工作量的味道了
@netwjx 感谢,看来终究还是绕不开这个操作呀=.=