等待在nodejs中正确连接到Rabbit

时间:2019-02-27 21:05:34

标签: javascript node.js rabbitmq node-amqplib

我尝试为amqplib / callback_api编写简单的事件发射器包装。当兔子不可用或没有连接时,我无法处理情景警示。 我有方法getConnect返回Promise,它在建立连接时解析。但是,如果连接被拒绝,Promise显然会拒绝。如何强制这种方法在不建立连接的情况下重新连接

/**
     * Async method getConnect for connection
     * @returns {Promise<*>}
     */
    getConnect = async () => {
        return new Promise((resolve, reject) => {
            amqp.connect(this.config.url, async function(err, conn) {
                    if (err) {
                        reject(err);
                    }
                    resolve(conn);
            })
        })
    };

整个代码在https://github.com/kimonniez/rabbitEE

也许,我已经很困了,但我完全感到困惑:)预先感谢!

2 个答案:

答案 0 :(得分:1)

Promise包裹在Observable

Promise不能处理“重试” 逻辑。如果要这样做,则应使用rxjs library查看 Observables 。这样可以在捕获错误的同时使用任意时间间隔重试。

const { from, interval, of } = rxjs;
const { catchError, mergeMap, tap, skipWhile, take } = rxjs.operators;

const THRESHOLD = 3;
const RETRY_INTERVAL = 1000;

// Equivalent to 'amqp.connect'
const functionThatThrows = number =>
  number < THRESHOLD
    ? Promise.reject(new Error("ERROR"))
    : Promise.resolve("OK");

// Equivalent to `getConnect`
const getConnect = () =>
  interval(RETRY_INTERVAL)
    .pipe(
      mergeMap(x => from(functionThatThrows(x)).pipe(catchError(e => of(e)))),
      skipWhile(x => {
        const isError = x instanceof Error;
        if (isError) console.log('Found error. Retrying...');
        return isError;
      }),
      take(1)
    ).toPromise();

// Resolve only if the inner Promise is resolved
getConnect().then(console.log);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.4.0/rxjs.umd.min.js"></script>

说明

  1. 使用interval中的1000创建源。表示它将每秒重试
  2. 致电您的amqp.connect,相当于我的示例中的functionThatThrows
  3. 使用catchError运算符捕获错误并返回错误
  4. 在返回的对象为错误时跳过。这样,只有在您的Promise已解决但未被拒绝的情况下,您才能解决
  5. 使用take(1)
  6. 获取第一个已解决的结果
  7. 使用toPromise实用程序功能将可观察的转换为诺言
  8. 调用函数并像使用标准then一样附加Promise

答案 1 :(得分:0)

如果您只想一直尝试连接直到建立连接,则可以将getConnect方法包装到新的keepConnect方法中:

keepConnect = async () => {
   while (true) {
      try {
         let conn = await getConnect()
         return conn
      } catch (e) {}
  }
}

但是我认为最好通过更改while条件来实现“尝试连接n次”之类的方法。通常,“ while true”解决方案不是干净的,可能会导致性能下降,并可能减慢事件循环的速度(假设connect方法总是在几毫秒内返回错误)。

您还可以使用keepConnect包装器来实现连接尝试之间的逐步延迟系统。

如果您想在连接断开时重新连接,则与Rabbit(我不知道)及其事件有关。