我正在尝试实现套接字,其中用户请求带有 id 的函数,并且在拥有 id 后,我每秒都会点击一个 api 并向用户发出响应
问题:每当新用户请求相同的 id 时,它都会再次调用具有相同 id 的相同 api
目标:我试图实现如果 setInterval 已经使用相同的 id 运行,那么它不应该再次调用,而只是开始发出响应。
我的代码:
socket.on('fancy' , async (data) => {
checkInterval = setInterval(async _ => {
callapi(data.match_id).then( fancy => {
socket.emit(`fancy_${data.match_id}`, fancy)
})
}, 1000)
})
callapi = (id) => {
var options = {
'method': 'POST',
'url': 'url',
formData: {
'id': id
}
};
return new Promise((resolve, reject) => {
request(options, function (error, response) {
let resp = {}
if (error) reject(error)
resolve({status: 'success', data: JSON.parse(response.body).data})
});
})
}
任何建议都会有很大帮助!
我处理这个问题的方法是创建一个
Class
来处理多种幻想 -
为了完整起见,这是我昨天在评论中发送的内容 - 它解决了问题中的要求。
class Fancy {
static fancies = {};
static add(match_id, socket) {
if (!Fancy.fancies[match_id]) {
Fancy.fancies[match_id] = new Fancy(match_id);
}
Fancy.fancies[match_id].subscribe(socket);
}
subscribers = [];
constructor(match_id) {
this.match_id = match_id;
this.checkInterval = setInterval(async () => {
const fancy = await callapi(this.match_id);
this.subscribers.forEach((socket) =>
socket.emit(`fancy_${this.match_id}`, fancy)
);
});
}
subscribe(socket) {
if (!this.subscribers.find((sock) => sock === socket)) {
this.subscribers.push(socket);
}
}
}
socket.on('fancy' , ({match_id}) => Fancy.add(match_id, socket));
注意:虽然这是一个
class
- 仅需要使用静态 add
方法。
当然,这不能处理断开连接,也不能处理用户从“幻想”中“取消订阅”的能力 - 根据评论
因此,要扩展该代码,它并没有太大不同 - 只需添加几个静态方法和一些实例方法
remove
静态方法 - 现有add
的逆方法,以及从所有实例中删除套接字的disconnect
静态方法。
对于实例方法,添加
unsubscribe
、start
和 stop
方法
class Fancy {
static fancies = {};
static add(match_id, socket) {
if (!Fancy.fancies[match_id]) {
Fancy.fancies[match_id] = new Fancy(match_id);
}
Fancy.fancies[match_id].subscribe(socket);
}
static remove(match_id, socket) {
Fancy.fancies[match_id]?.unsubscribe(socket);
}
static disconnect(socket) {
Fancy.fancies.forEach(fancy => fancy.unsubscribe(socket));
}
// instance properties/methods
subscribers = [];
constructor(match_id) {
this.match_id = match_id;
}
start() {
if (!this.checkInterval) {
this.checkInterval = setInterval(async () => {
const fancy = await callapi(this.match_id);
this.subscribers.forEach((socket) =>
socket.emit(`fancy_${this.match_id}`, fancy)
);
});
}
}
stop() {
clearInterval(this.setInterval);
this.checkInterval = null;
}
unsubscribe(socket) {
this.subscribers = this.subscribers.filter(sock => sock !== socket);
if (this.subscribers.length === 0) {
this.stop();
}
}
subscribe(socket) {
if (!this.subscribers.find((sock) => sock === socket)) {
this.subscribers.push(socket);
if (this.subscribers.length === 1) {
this.start();
}
}
}
}
socket.on('fancy' , ({match_id}) => Fancy.add(match_id, socket));
socket.on('unfancy' , ({match_id}) => Fancy.remove(match_id, socket));
socket.on('close', () => Fancy.disconnect(socket));
stop
/start
方法的替代方法是保持间隔运行,但仅在有任何“订阅者”时才发出 API 请求
这稍微简化了代码,只需添加一个实例方法(取消订阅)
类似这样的:
class Fancy {
static fancies = {};
static add(match_id, socket) {
if (!Fancy.fancies[match_id]) {
Fancy.fancies[match_id] = new Fancy(match_id);
}
Fancy.fancies[match_id].subscribe(socket);
}
static remove(match_id, socket) {
Fancy.fancies[match_id]?.unsubscribe(socket);
}
static disconnect(socket) {
Fancy.fancies.forEach(fancy => fancy.unsubscribe(socket));
}
// instance properties/methods
subscribers = [];
constructor(match_id) {
this.match_id = match_id;
this.checkInterval = setInterval(async () => {
if (this.subscribers.length) {
const fancy = await callapi(this.match_id);
this.subscribers.forEach((socket) =>
socket.emit(`fancy_${this.match_id}`, fancy)
);
}
});
}
unsubscribe(socket) {
this.subscribers = this.subscribers.filter(sock => sock !== socket);
}
subscribe(socket) {
if (!this.subscribers.find((sock) => sock === socket)) {
this.subscribers.push(socket);
}
}
}
就我个人而言,我会使用最后一个解决方案,当没有订阅者时,设置一个实际上不执行任何操作的时间间隔不会对性能造成影响