Search code examples
node.jsrabbitmqnode-amqplib

How can I build a class to abstract RabbitMQ and amqplib functionality in Node.js


I am trying to build a small library to abstract some of the boilerplate needed with amqplib to communicate with RabbitMQ. I am using the promises api and the async/await syntax. I am trying to build a class with some methods to use with several other servers and clients. I have searched online and the vast majority of the examples are direct, small scale tutorials.

Here is what I have so far for messages.js:

const amqp = require('amqplib');

module.exports = class MQ {
    constructor(user, password, host, port) {
        this.conn;
        this.uri = 'amqp://' + user + ':' + password + '@' + host + ':' + port;
        this.channel;
        this.q = '';
    }
    async setupConnection() {
        this.conn = await amqp.connect(this.uri);
        this.channel = await this.conn.createChannel();

        await this.channel.assertQueue(this.q, { durable: false });
    }   

    send(msg) {
        this.channel.sendToQueue(this.q, Buffer.from(msg));
        console.log(' [x] Sent %s', msg);
    }

    async recv() {
        await this.channel.consume(this.q), (msg) =>{
            const result = msg.content.toString();
            console.log(`Receive ${result}`);
        };
    }
}

Here is the code for setup.js:

const MQ = require('./message');

msgq = new MQ('guest', 'guest', 'localhost', '5672')

msgq.setupConnection();

msgq.send('Test this message');

The error I get when I try to send the message is "TypeError: Cannot read property 'sendToQueue' of undefined." Apparently the channel property is not being initialized properly. I enclosed the async/awaits in try/catch blocks and get the same error.

Is there something I am missing about classes/methods in Node.js?

I think this has something to do with the resolution of the promises. When I move the call to sendToQueue() up to the setupConnection() method, the message gets sent.

So it seems that I need to find a way to have the send method wait on the resolution of the setup method.


Solution

  • You are not running your code asynchronously, so send is getting called before a connection has been established. You need to chain the promises to be guaranteed that the connection function has completed before trying to send. Try this:

    const MQ = require('./message');
    
    msgq = new MQ('guest', 'guest', 'localhost', '5672')
    
    msgq.setupConnection()
    .then(() => {
        msgq.send('Test this message');
    })