#node.js #rabbitmq #amqp
#node.js #rabbitmq #amqp
Вопрос:
итак, я использую RabbitMQ для некоторых проектов, и я заметил, что я все время буду использовать какой-то повторяющийся код, поэтому я решил создать класс-оболочку или интерфейс, который имеет некоторую функцию для прямого использования RabbitMQ без постоянного повторения кода. я начал это делать вчера, и у меня уже были некоторые проблемы, так как я хотел использовать ООП, а Javascript может быть сложным при использовании ООП (по крайней мере, я так думаю)
Я начал с создания класса IRAbbitMQ с функцией init для инициализации соединения и создания канала, я знал, что не могу использовать вложенные классы, поэтому вместо этого я хотел использовать заводские функции, я попытался установить соединение и передать часть свойств класса IRabbitMQ, но я не знаю, почему это дало мне undefinedкогда я создаю его экземпляр
class IRabbitMQ {
constructor() {
this.init(rabbitMQServer); // rabbitMQServer for example 'localhost//5672'
}
// establish a Connection to RAbbitMQ Server
async init(host) {
try {
let connection = await amqplib.connect(host);
let channel = await connection.createChannel();
channel.prefetch(1);
console.log(' [x] Awaiting RPC requests');
this.connection = connection;
this.channel = channel;
}
catch(err) {
console.error(err);
}
}
// Close the Connection with RabbitMQ
closeConnection() {
this.connection.close();
}
log() {
console.log(this.connection);
}
EventPublisher() {
function init(IRabbit, publisherName) {
if(!IRabbit.connection) {
throw new Error('Create an Instance of IRabbitMQ to establish a Connection');
}
let ch = IRabbit.channel;
console.log(ch);
}
return {
init : init
}
}
}
var r = new IRabbitMQ();
r.log();
когда я запускаю код, результат не определен, я не знаю почему, поскольку я инициализирую свойства соединения и канала в функции init, а затем вызываю эту функцию в конструкторе, чтобы она инициализировалась при создании объекта класса-оболочки. я также хотел бы получить от вас несколько советов, полезно ли использовать классы или есть какой-либо другой лучший способ создать класс-оболочку или интерфейс для RabbitMQ, чтобы упростить его использование и не дублировать код.
Комментарии:
1. Не могли бы вы уточнить «вывод не определен», что означает, что он где-то регистрирует «undefined»? Мне просто непонятно, где / что происходит сбой 🙂
2. существует функция с именем log(), которая будет console.log(this.connection) , с помощью этой функции я проверил, произошло ли подключение к rabbitmq или нет. Когда я вызываю эту функцию, это консоль. log undefined вместо соединения это означает, что свойство класса connection имеет значение undefined вместо реального соединения, и это меня смущает, потому что, когда я утешаю. регистрируйте свойство connection изнутри функции init, чем оно работает, и регистрирует реальный объект connection. надеюсь, это поможет вам понять вопрос
3. Ну, в этом случае у вас, вероятно, есть условие гонки? Конструктор вызывает
init()
который является асинхронным. Итак, когда вы создаете экземпляр объекта, а затем вызываете напрямую.log()
, есть вероятность, чтоinit()
он еще не завершен, поскольку в этот момент он асинхронен. Например, заводская функция была бы лучшеconst myRabbit = await RabbitMQFactory.create()
. Не особенноawait
перед заводской функцией.4. он также не работал с заводской функцией: (может быть, вы можете показать мне какой-нибудь код, если он работает с вами, это было бы полезно
Ответ №1:
На самом деле это не ответ, но я смог успешно войти в connection
систему с помощью этого примера кода. Я вырезал другой код, чтобы просто сосредоточиться на той .log()
части, которая регистрировала a undefined
.
Код далек от совершенства, но работает, по крайней мере
const amqplib = require('amqplib');
class IRabbitMQ {
constructor() { }
async init(host) {
try {
const connection = await amqplib.connect(host);
const channel = await connection.createChannel();
channel.prefetch(1);
console.log(' [x] Awaiting RPC requests');
this.connection = connection;
this.channel = channel;
}catch(err) {
console.error(err);
}
}
log() {
console.log(this.connection);
}
}
async function createInstance(){
const instance = new IRabbitMQ();
try {
await instance.init('amqp://localhost');
}catch (e) {
throw new Error('OOPS!');
}
return instance;
}
async function runLogic() {
const r = await createInstance();
r.log();
}
runLogic().catch(console.log);
Просто прокомментируйте, если вы хотите, чтобы я дал дополнительные советы / подсказки, но, похоже, это работает для меня.
Комментарии:
1. Я очень благодарен вам за усилия, хотя может показаться, что это работает нормально, но, как вы сказали, это немного запутанно, если мой класс будет структурирован таким образом, и, как я написал в описании, моя цель на самом деле состоит в том, чтобы создать оболочку класса для обертывания некоторых функций, чтобы я могмне не нужно все время повторяться и писать какой-то код spaguetti. это работает так, как вы делаете, но моей целью было не регистрировать свойство connection, я хотел, чтобы соединение с rabbitmq было доступно как свойство, чтобы я мог использовать его для других классов или функций.
2. возможно, этот комментарий поможет больше, цель состоит в том, чтобы обернуть все функции публикации и подписки в класс, чтобы в файле publisher мне требовался только этот класс, а затем создать экземпляр и вызвать функции, которые отвечают за публикацию сообщения, и если мне нужно подписаться, я перейду кфайл subscribe и создайте экземпляр этого класса, а затем вызовите функции, ответственные за подписку. этот способ организует мою работу, и если бы у меня была команда, тогда было бы лучше поддерживать код. я надеюсь, что это поможет, и я большое спасибо вам и всем, кто пытается помочь 🙂
3. Я лично не стал бы пытаться принудительно использовать класс. Вам нужно что-то «одноэлементное» на случай, если вы хотите повторно использовать одно и то же соединение (верно?). Если это предположение верно, я бы просто вернул из вашего модуля узла объект с нужными вам методами и сохранил ваше состояние (например, соединение) в виде clojure в вашем файле.
4. в этой ситуации проблема будет заключаться в том, что я не могу назначить соединение свойству класса или вернуть его из функции. например, в функции init, когда я назначаю this.connection = connection и когда я хочу вызвать это свойство connection в другой функции или из экземпляра класса, это соединение будет неопределенным, и я не знаю почему. если я забыл класс и использую только функцию, которая подключается к rabbitmq, а затем возвращает connection, а затем использует его в своем коде для exp let c = establishConnection(); // здесь я получаю также undefined, я не знаю, почему