【发布时间】:2019-07-08 10:19:23
【问题描述】:
我正在创建一个递归系统,它重新发送 socket.io 数据包,直到服务器通过完成 socket.io 确认来回答。我创建了一个承诺,它将在 X 秒内拒绝或解决如果服务器及时回答,如果它超时,我会重新创建一个超时时间更长的承诺。
问题是当之前至少有一次超时时,确认无法解决承诺,我不明白为什么。
这是我的代码的 sn-p :
async emit(event, data) {
if (!this.socket) {
this.eventToSend[event] = data;
}
let timeoutRef;
let alreadyResolved = false;
return new Promise(async r => {
const sentPromise = timeout => {
return new Promise((resolve, reject) => {
console.log("------ New Call ------");
timeoutRef = setTimeout(() => {
if (alreadyResolved === true) {
console.log("Promise with timeout : " + timeoutRef + " is already resolved !!!");
} else {
console.log("promise " + timeoutRef + " timeouted !");
reject();
}
}, timeout);
console.log("Create promise with Timeout number : " + timeoutRef);
this.socket.emit(event, { data }, function(response) {
alreadyResolved = true;
console.log("try to delete " + timeoutRef + " timeout");
resolve(response);
});
});
};
try {
const result = await this.recursiveSend(sentPromise);
console.log("received the result " + result + ", aborting the process");
r(result);
} catch (e) {
console.error(e);
this.socket.disconnect(true);
}
});
}
async recursiveSend(promise, retryIndex = 0) {
try {
const result = await promise(this.timeoutRate[retryIndex]);
console.log("recevied result ! " + result);
return result;
} catch (e) {
// Here the setTimeout executed before I received the server acknowledgement
const newRetryIndex = retryIndex + 1;
if (newRetryIndex >= this.timeoutRate.length) {
throw new Error("Timeout exceeded, unable to join the socket");
} else {
return this.recursiveSend(promise, newRetryIndex);
}
}
}
这是实际的控制台日志输出:
...
------ New Call ------
Create promise with Timeout number : 32
promise 32 timeouted !
------ New Call ------
Create promise with Timeout number : 34
promise 34 timeouted !
------ New Call ------
Create promise with Timeout number : 36
try to delete 36 timeout // Here the promise is supposed to be resolved
Promise with timeout : 36 is already resolved !!! // But here we tried to reject it
日志不可靠,所以我尝试使用断点,我仍然先进入resolve()(但我无法进入),然后进入reject()。这就像 socket.io 确认是在另一个线程中进行的,但是当没有超时并且服务器立即响应时它可以完美运行
【问题讨论】:
-
究竟何时调用
this.socket.emit的回调?您是否在“旧”发出回调中得到确认,而不是在重试中得到确认? -
我删除了异步函数并简单地返回了promise,似乎它没有改变任何东西......服务器在收到第一个请求后6秒响应。我不明白你的最后一个问题,确认只在最后一个电话中收到
-
你怎么知道这是最后一个电话?您的
timeoutRef和alreadyResolved变量是全局变量。尝试将他们的声明放在sentPromise函数中。 -
所以您说您没有收到“recevied result !”和“received the result ... aborting the process”日志,但希望他们?
标签: javascript node.js promise socket.io settimeout