Geek Guy
Geek Guy

Reputation: 702

Nodejs MQTT: unsubscribe is not a function

I have inplemented MQTT well but I am experiencing an issue with unsubscribe method. All other functions (mqttCon.publish() , mqttCon.subscribe(), mqttCon.on()...) are working well except this. I have checked the spelling and even done ctrl +click and it takes me to the library implementation meaning it is the right method and referenced well yet I keep getting the error below. How can I solve it?

This is the line: mqttCon.unsubscribe(topic)

TypeError: mqttCon.unsubscribe is not a function

    at noopHandler (/home/dev/project-dir/src/mqtt/processMessage.js:5:13)
    at module.exports (/home/dev/project-dir/src/mqtt/processMessage.js:10:20)
    at MqttClient.client.on (/home/dev/project-dir/src/mqtt/mqttCon.js:16:13)
    at MqttClient.emit (events.js:189:13)
    at MqttClient._handlePublish (/home/dev/project-dir/node_modules/mqtt/lib/client.js:1271:12)
    at MqttClient._handlePacket (/home/dev/project-dir/node_modules/mqtt/lib/client.js:410:12)
    at work (/home/dev/project-dir/node_modules/mqtt/lib/client.js:321:12)
    at Writable.writable._write (/home/dev/project-dir/node_modules/mqtt/lib/client.js:335:5)
    at doWrite (/home/dev/project-dir/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:428:64)
    at writeOrBuffer (/home/dev/project-dir/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:417:5)

NOTE: I am using ES6(Emacscript 6+) javascript and not Typescript. Nodejs 12.18.1 and npm 6.14.6

Here is my connection code mqttCon.js:

const mqtt = require('mqtt')
const processMessage = require('./processMessage')
const logger = require('../logConf')
const options = {
    host: '',
    port: '',
    username:'',
    password: '',
    protocol: ''
};
const client = mqtt.connect(options)
client.on("connect", function () {
    console.log("MQTT connected  with status: " + client.connected);
    if (client.connected) {
        client.on('message', (topic, message) => {
            processMessage(topic, String(message))
        })
    }
})
client.on('error', error => {
    console.log(error,'ERROR')
    logger.errorLogger.error(error)
})
client.on('reconnect', error => {
    console.log(error,'RECONNECT')
    logger.errorLogger.error(error)
})
client.on('close', error => {
    console.log(error,'CLOSE')
    logger.errorLogger.error(error)
})
client.on('disconnect', error => {
    console.log(error,'DISCONNECT')
    logger.errorLogger.error(error)
})
client.on('offline', error => {
    console.log(error,'OFFLINE')
    logger.errorLogger.error(error)
})
module.exports = client

This is the processMessage.js :

const mqttCon = require('./mqttCon')
const logger = require('../logConf')
let noopHandler = (topic, message) => {
    console.log(String(message))
    mqttCon.unsubscribe(topic)    //THIS IS WHERE THE ERROR IS OCCURRING *******************
}
module.exports = (topic, message) => {
    switch (topic) {
        case 'NOOOOOOOOOOOOOOOOOOOOOOOOP':
            return noopHandler(topic, message)
        case 'anotherTopic':
            // return handleAnotherTopic(String(message))
            return
        default:
            logger.errorLogger.error(new Error(`No handler for topic ${topic}`))

    }
}

Upvotes: 0

Views: 1058

Answers (1)

JD Allen
JD Allen

Reputation: 944

Your mqttCon.js file has no client.prototype.unsubscribe = function() {}, so the error is correct. You are defining client as a module, but you are really needing to call mqtt.unsubscribe() somewhere. So you need to either add an unsubscribe() function to the client constant (which really should be a var in this case), or call the mqtt.unsubscribe() function after requiring the mqtt module in your processMessage.js file....which I think goes against what you are trying to do anyway. You might want to read up a bit more about how module.exports actually works: https://www.sitepoint.com/understanding-module-exports-exports-node-js/

UPDATE: The above influenced my thoughts and the issue was that I was importing processMessage.js which inturn imports mqttCon.js which imported it. Circular import, meaning mqttCon(mqttClient) was always not yet initialized inside processMessage.js. The solution was that I imported processMessage.js inside client.on('connect'....)... block when client is already initialized and exported well as a module like below:


client.on("connect", () => {
    console.log("MQTT connected  with status: " + client.connected);
    if (client.connected) {
        client.on('message', (topic, message) => {
            require('./processMessage')(topic, String(message))
        })
    }
})

Upvotes: 1

Related Questions