arcoirislabs / cordova-plugin-mqtt

MqTT Cordova Plugin for Apache Cordova (> v3.0)
MIT License
86 stars 49 forks source link

Messages listener logic as standart paho.js #16

Closed 4refr0nt closed 8 years ago

4refr0nt commented 8 years ago

At now, we must add listeners to every subscribed topic, but usually, enough one listener for all received messages from all subscibed topics. Also, we can't remove listener (mqtt-emitter not support removeListener) now. If we want receive messages from one topic, then we must:

Easy way, may be: we subscribing to some topics (may be wildcard) and receive all messages from subscribed topics by one listener onMessageArrived (as paho.js cb onMessageArrived). After unsubscribing, this listener will not receive messages from unsubsribed topics, but receive from subscribed.

I'm use this method on version 0.2.7 cordova-plugin-mqtt by replacing cordova.fireDocumentEvent(cd.topic,cd); to cordova.fireDocumentEvent("onMessageArrived",cd); and receiving all messages, include subscribed wildcards topics too (prefix/+/+/suffix , prefix/# and other) by one listener without thinking about other listeners.

arcoirislabs commented 8 years ago

Hello @4refr0nt You can use the onPublish callback in the connect method if you want to place the listeners in a single callback like this

cordova.plugins.CordovaMqTTPlugin.connect({
    url:"tcp://test.mosquitto.org", //a public broker used for testing purposes only. Try using a self hosted broker for production.
    port:1883,
    clientId:"YOUR_USER_ID_LESS_THAN_24_CHARS",
    connectionTimeout:3000,
    willTopicConfig:{
        qos:0, //default is 0
        retain:true, //default is true
        topic:"<will topic>",
        payload:"<will topic message>"
    },
    username:"uname",
    password:'pass',
    keepAlive:60,
    success:function(s){
        console.log("connect success");
    },
    error:function(e){
        console.log("connect error");
    },
    onConnectionLost:function (){
        console.log("disconnect");
    },
    onPublish:function(topic,payload){
         //here you can listen to every topic's payload, this is similar to onMessageArrived in paho.js
    }
});

In version 0.2.7, we implemented the document's event listener. But as it is observed, the event listeners are not actually "removed" unless the element they are attached to is removed, which is document in our case, hence unless the document object is destroyed, the event listener still remains as the object, but is never called when triggered, which in turn becomes a memory leak.

In this latest version, we used topic routing because some developers actually requested for the support of wildcard topics across different scopes in their javascript application. Also we wanted to reduce the overhead on the Cordova app that may be caused by this plugin. The topic routing approach works really well if you are using any frameworks like AngularJS or even a some UI frameworks like Framework7, where you can separate the connection scope and the operational (publish, subscribe & listen). But there are also the developers who would prefer a single callback like onMessageArrived in paho.js for the simplicity & for them we have implemented the onPublish method as shown above. But the disadvantage of the onPublish method is that, if you subscribe to a wildcard topic (could be single level or multi level), it is upto the developer to regex the current topic with the wildcard topic, the developer actually subscribed to. To address that issue, we actually integrated a topic router that will give you a sound and fair access to any topics, especially the wildcard topics & for non-wildcard topics, you can use the onPublish method.

The topic router actually helps you access and control the wildcard topics in a very intuitive way. Suppose you subscribe to a topic as prefix/+/+/suffix. You can turn this topic into a topic pattern to listen from the listen method in this way prefix/+first/+second/suffix where you can actually access the individual single levels of the topics to look for specific topic level characters via first & second variables. The duplicity prevention is managed by the topic router itself based on what patterns you use. Hence if you remove a listener based on a certain topic pattern you may stop listening to it. And the implementation is completely memory safe, which is why we chose to implement it in this plugin. Also the listener is initiated when you call the listen method & not when the router object emits it.

I hope I have answered your question

Regards, Amey Kshirsagar, Maintainer