我有一个
connect()
函数,它返回一个承诺(它实际上是类中的一个方法 - 未显示)。如果未建立连接(即当连接尝试中发生错误时),我希望此函数延迟重试,但到目前为止我无法使其工作。
我尝试使用 async js 库和 Promise-retry 库但无济于事 - 文档很难理解。为了清楚起见,如果建立连接,
socket.connect
会发出“连接”事件。
这是我的代码:
this.socket = new net.Socket();
this.client = new Modbus.client.TCP(this.socket, this.unitID);
const net = require('net');
const Modbus = require('jsmodbus');
connect() {
return new Promise((resolve, reject) => {
this.socket.connect(options);
this.socket.on('connect', () => {
logger.info('*****CONNECTION MADE*****');
//does something once connection made
resolve();
});
this.socket.on('error', (error) => {
logger.error('failed to connect');
this.disconnect();
reject();
});
})
}
首先定义一个具有延迟的效用函数:
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
然后将
.catch
处理程序链接到 new Promise
:
.catch(() => delay(1000).then(() => this.connect()));
当然,您应该避免无限次的重试。因此,实现一些逻辑来明确放弃:在固定次数的尝试之后,或者在经过一定时间之后,......等等
例如,给
connect
一个参数,它应该允许多少次尝试:
connect(attempts=3) {
那么 catch 处理程序可以是:
.catch((err) => {
if (--attempts <= 0) throw err; // give up
return delay(1000).then(() => this.connect(attempts));
});
我会通过创建执行单次连接尝试的函数来实现这一点(基本上,将您的
connect
重命名为 tryConnect
或类似的方法,如果您使用的是足够新的 Node.js 版本,甚至可以作为私有方法) ),然后有一个函数通过重复和延迟来调用它,就像这样(见评论):
实用功能:
function delay(ms, value) {
return new Promise(resolve => setTimeout(resolve, ms, value);
}
新的
connect
:
async connect() {
for (let attempt = 0; attempt < MAX_ATTEMPTS; ++attempt) {
if (attempt > 0) {
// Last attempt failed, wait a moment
await delay(RETRY_DELAY_IN_MS);
}
try {
await tryConnect();
return; // It worked
} catch {
}
}
// Out of retries
throw new Error("Couldn't create connection");
}
(如果您使用的是稍旧的 Node.js,您可能需要在上面的
(e)
之后添加 catch
。当您不需要它时将其保留是一个相对较新的功能。)
关于我所说的当前实现
tryConnect
,这里有一些注释作为我如何更改它的注释:
tryConnect() {
return new Promise((resolve, reject) => {
// Keep these local for now
const socket = new net.Socket();
const client = new Modbus.client.TCP(socket, this.unitID);
// Add handlers before calling `connect
socket.on('connect', () => {
logger.info('*****CONNECTION MADE*****');
// NOW save these to the instance and resolve the promise
this.socket = socket;
this.client = client;
resolve();
});
socket.on('error', (error) => {
logger.error('failed to connect');
// It's not connected, so no `disconnect` call here
reject();
});
socket.connect(options);
});
}
在调用connect的函数中, 可以递归调用,eg
const outerFunction = (times = 0) => {
if (times < 4) {
socket
.connect(params)
.then(() => {
// do good stuff
})
.catch(e => {
// increment the times so that it wont run forever
times++;
setTimeout(() => {
// delay for two seconds then try conecting again
outerFunction(times);
}, 2000);
});
}
};
这样你的连接功能会以2秒的间隔尝试3次,我希望这可以解决你的问题