延迟重试承诺,直到在 NodeJS 中解决
Retry promise with delay until resolved in NodeJS
我提前道歉,因为我是编程新手,而且我已经坚持了很长一段时间。我有一个 connect() 函数,它 returns 一个承诺(它也嵌入在 class - 未显示)。如果未建立连接(即返回拒绝),我希望此功能延迟重试,但我一直无法这样做;我尝试使用异步 js 库和 promise-retry 库无济于事 - 我无法理解文档。为清楚起见,如果建立连接,socket.connect 会发出 '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((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,您可能需要在上面的 catch
之后添加 (e)
。不使用时将其关闭不需要它是一个相对较新的功能。)
关于你当前对我所说的实现 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);
});
}
};
这样你的connect函数就以2秒的间隔尝试了3次,希望能解决你的问题
我提前道歉,因为我是编程新手,而且我已经坚持了很长一段时间。我有一个 connect() 函数,它 returns 一个承诺(它也嵌入在 class - 未显示)。如果未建立连接(即返回拒绝),我希望此功能延迟重试,但我一直无法这样做;我尝试使用异步 js 库和 promise-retry 库无济于事 - 我无法理解文档。为清楚起见,如果建立连接,socket.connect 会发出 '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((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,您可能需要在上面的 catch
之后添加 (e)
。不使用时将其关闭不需要它是一个相对较新的功能。)
关于你当前对我所说的实现 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);
});
}
};
这样你的connect函数就以2秒的间隔尝试了3次,希望能解决你的问题