延迟重试 Promise,直到在 NodeJS 中解决为止

问题描述 投票:0回答:3

我有一个

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();
        });
    })
}
javascript node.js promise delay
3个回答
3
投票

首先定义一个具有延迟的效用函数:

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));
});

0
投票

我会通过创建执行单次连接尝试的函数来实现这一点(基本上,将您的

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);
    });
}

0
投票

在调用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次,我希望这可以解决你的问题

© www.soinside.com 2019 - 2024. All rights reserved.