WebSocket React Native - javascript

I'm new to react native moved from ReactJS I thought I can use same packages as my previous pure Reactjs app but I was wrong.
What I'm trying to do is to make a websocket connection.
I'm recently using autobahnJS package WAMP2 in my ReactJS app but when I moved to react native it seems autobahnJS doesn't support react-native
connectToSocketFunction = () =>{ // autobahn code
let connection = new autobahn.Connection({ url: 'wss://api.example.com/websocket/', realm: 'Realm1', authmethods: ['jwt'] });
connection.onopen = (session, detalis) => {
session.subscribe('ChannelName', (data)=>console.log(data));
};
Anyone know how does react native make socket connection based on my code?
I have tried react-native-autobahnjs doesn't work

The React Native documentation mentions support for WebSocket connections:
var ws = new WebSocket('ws://host.com/path');
ws.onopen = () => {
// connection opened
ws.send('something'); // send a message
};
ws.onmessage = (e) => {
// a message was received
console.log(e.data);
};
ws.onerror = (e) => {
// an error occurred
console.log(e.message);
};
ws.onclose = (e) => {
// connection closed
console.log(e.code, e.reason);
};
https://facebook.github.io/react-native/docs/network.html#websocket-support
You will most likely need to use other React Native based frameworks to fill in the gaps that Autobahn provided, e.g. session support and JWT authentication.

Related

Subscribing to Azure Pub Sub web service from react causes Unhandled Rejection (TypeError)

Based on the official documentation, i am able to get the subscribed messages. When i simply run the javascript code, it runs without any error.
const WebSocket = require('ws');
const { WebPubSubServiceClient } = require('#azure/web-pubsub');
async function main() {
const hub = "hub1";
let service = new WebPubSubServiceClient(process.env.WebPubSubConnectionString, hub);
let token = await service.getClientAccessToken();
let ws = new WebSocket(token.url);
ws.on('open', () => console.log('connected'));
ws.on('message', data => console.log('Message received: %s', data));
}
main();
But when i try to do this within React class's, componentDidMount() function, facing error.
import React from "react";
// == Azure WebPuSub
// import { WebPubSubServiceClient } from '#azure/web-pubsub';
// import { WebSocket } from 'ws';
const { WebPubSubServiceClient } = require('#azure/web-pubsub');
const WebSocket = require('ws');
class AzurePubSubTest extends React.Component {
constructor(_props, _context) {
super(_props, _context);
this.connectToPubSub = this.connectToPubSub.bind(this);
this.state = {
}
}
async componentDidMount() {
console.log("===Mounting....")
await this.connectToPubSub();
}
componentWillUnmount() {
console.log("Unmounting....")
}
async connectToPubSub() {
const hub = "hub1";
let endpoint;
// endpoint = process.env.WebPubSubConnectionString;
endpoint = "Endpoint=https://***check.webpubsub.azure.com;AccessKey=***;Version=1.0;"
// endpoint = "wss://***check.webpubsub.azure.com/client/hubs/Hub?access_token=***";
console.log("process.env.WebPubSubConnectionString");
console.log(endpoint);
let service = new WebPubSubServiceClient(endpoint, hub);
let token = await service.getClientAccessToken();
let ws = new WebSocket(token.url);
ws.on('open', () => console.log('connected'));
ws.on('message', data => console.log('Message received: %s', data));
}
render() {
const user = { username: "Check" };
let testMessages = [];
if (testMessages === undefined || testMessages === null) {
testMessages = [];
}
return (
<div>Testing....</div>
)
}
}
export default AzurePubSubTest;
× Unhandled Rejection (TypeError): Right-hand side of 'instanceof' is
not an object
Stacktrace 1
Stacktrace 2
Stacktrace 3
The issue here is with the Jsonwebtoken package which is used with the websocket.
Jsonwebtoken is predominantly build for NodeJS to be run on a web server so it doesn't fully work with the client-side rendering of the react apps
try installing the latest version of jsonwebtoken , otherwise the ideal way of working would be with an intermediary between the react app and azure pub sub.
One workaround with this approach would be with azure function with azure web pub sub input/output bindings. and then use a WebSocket in the react app to connect to the azure function.
Here you will need a HTTP trigger with the input bindings of the azure pub sub . This trigger will return the URL which you can use in web sockets of your react app.
function.json (for http trigger) :
{
"bindings":[
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req"
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"type": "webPubSubConnection",
"name": "connection",
"hub": "notification",
"direction": "in"
}
]
}
Here I am sending the message using a time trigger and in a simple HTML file I created a WebSocket the html file which is served using different HTTP trigger. Thus after every interval of time I will get messages

Websocket memory leak node.js. Event emitters?

I am getting the event emitter leak after using my code 10 times essentially. I understand the default of event emitter auto sending out a warning in the console. My question is what in this code is directly creating the event listeners? Is it poor coding on my part or is it just how the websockets are stacked onto each other?
I'll explain the code a bit. I have one websocket within another and I figured it would serve the data to a web page essentially flowing from Twitch to a localhost site. However, if I use the keywords more than 10 times, I get the error. I do not understand enough about WebSockets to really understand why my code creates a new listener with each msg.text received so anyone with a bit more understanding please help!
I believe me issue to be similar to this though I am having a hard time conceptualizing my own code here
const { paintballShot } = require('./JavaScript/paintballGunFire');
const { readPin } = require('./JavaScript/readPin');
const ws = require('ws');
const express = require('express');
const app = express();
//CONNECT TO TWITCH
let client = new ChatClient({
connection: {
type: "websocket",
secure: true,
}
});
//connected?
client.on("ready", () => console.log("Successfully connected to chat"));
client.on("close", (error) => {
if (error != null) {
console.error("Client closed due to error", error);
}
});
//create headless websocket
const wsServer = new ws.Server({ noServer: true });
wsServer.on('connection', function connection(socket) {
//call other websocket connected to Twitch from inside the new websocket
client.on("PRIVMSG", (msg, error) => {
if (msg.messageText === "right") {
socket.send(JSON.stringify(`${msg.displayName}: ${msg.messageText}`));
}
if (msg.messageText === "left") {
socket.send(JSON.stringify(`${msg.displayName}: ${msg.messageText}`));
}
if (msg.messageText === "fire") {
socket.send(JSON.stringify(`${msg.displayName}: ${msg.messageText}`));
paintballShot();
}
if (msg.messageText === "pin") {
readPin();
}
process.on('uncaughtException', function (err) {
console.log(err);
});
});
client.connect();
client.join("channel");
socket.on('message', message => console.log(message));
});
// `server` is a vanilla Node.js HTTP server
const server = app.listen(3000);
server.on('upgrade', (request, socket, head) => {
wsServer.handleUpgrade(request, socket, head, socket => {
wsServer.emit('connection', socket, request);
});
});
process.on('uncaughtException', function (err) {
console.log(err);
});
To wrap this up, the library I am using (Dank TwitchIRC) does have a connection rate limiter that seems to work if you add it to your chat client in the beginning. If I set it low enough, depending on the messages received from Twitch, it will end connections just as fast, meaning no memory leak.

QueueEvents don't trigger with BullMQ using Heroku Redis

I'm trying to implement a queue in NodeJS using BullMQ but i have some issues in production when trying to use a remote Redis (Heroku Redis or Redis Cloud).
In local, everything work well but when i try to use a REDIS_URL, a job is created but events doesn't work.
Here is the code:
// test_job.js
import { Queue, Worker, QueueEvents } from "bullmq";
import IORedis from "ioredis";
import Dotenv from "dotenv";
Dotenv.config();
// Good
const connection = new IORedis(process.env.REDIS_URL || 6379);
// Good
const queue = new Queue("Paint", { connection });
// Good
const worker = new Worker(
"Paint",
async job => {
if (job.name === "cars") {
console.log(job.data.color);
}
},
{ connection }
);
/**
* BUG HERE: Events work in local but not when using a remote Redis (REDIS_URL)
*/
const queueEvents = new QueueEvents("Paint");
queueEvents.on("completed", jobId => {
console.log("done painting");
});
queue.add("cars", { color: "blue" });
const queueEvents = new QueueEvents("Paint", { connection: connection.duplicate() });
https://github.com/taskforcesh/bullmq/issues/173

Log all queries using mongodb native driver for Node JS

Im relatively new to the MongoDB. At first I used mongoose, but now I decided to abandon it. Immediately I ran into the following problem: I can't understand how to print all the performed queries to the console.
In mongoose this could be done as simple as to write mongoose.set('debug', true), but how to do that using native driver?
I've read about Logger in the dcumentation, but the output seems completely unreadable for me. Is it possble to tune the output or i should just parse that somehow?
The Logger class no longer logs queries in version 4.0. You can do this instead:
const uri = "mongodb+srv://<user>:<password>#<cluster-url>?writeConcern=majority";
const client = new MongoClient(uri, { monitorCommands:true });
client.on('commandStarted', (event) => console.debug(event));
client.on('commandSucceeded', (event) => console.debug(event));
client.on('commandFailed', (event) => console.debug(event));
You should use the mongo's Logger class (see the official API doc):
const connect = async () => {
console.log("Connecting to database...");
try {
let client = await MongoClient.connect(uri, opts);
console.log("Database connected.");
Logger.setLevel("debug");
console.log("MongoDB Logger set to DEBUG");
} catch (e) {
console.log("ERROR: " + e.message);
}
};
The Logger class has multiple options (info, debug, error). They will log different types of database actions/events.

Unable to connect to WebSocket with Vue plugin

I'd like to write a vue-plugin to get handy WebSocket methods like connect() and subscribe() in my Vue application. I've got a problem with connecting to WebSocket, it only works when I call connect() method in the mounted hook and load the whole page (like with the browser refresh button). In another case, when I first load the page and then call the connect() method explicitly by the button click, the connection isn't established.
My vue-plugin code:
import SockJS from "sockjs-client";
import Stomp from "webstomp-client";
const WebSocketTester = {
install(Vue, options) {
console.log("websocket tester launched");
let connected = false;
const ws = {
connected: () => connected
};
const stompClient = getStompClient("http://localhost:8080/ws");
const connect = () => {
return new Promise((resolve, reject) => {
if (connected) {
reject("Already connected !");
return;
}
console.log("trying to connect websocket");
stompClient.connect({}, frame => {
console.log("got websocket frame:");
console.log(frame);
if (frame.command == "CONNECTED") {
connected = true;
resolve();
} else {
reject("Could not connect with " + url);
}
});
});
};
ws.connect = () => {
return connect();
};
Vue.prototype.$ws = ws;
}
};
const getStompClient = webSocketUrl => {
const socket = new SockJS(webSocketUrl);
return Stomp.over(socket);
};
export default WebSocketTester;
My vue component:
<template>
<div class="hello">
<button #click="connect">Connect with websocket</button>
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
msg: String
},
methods: {
connect() {
console.log("connecting...");
this.$ws.connect().catch(error => {
console.log("could not connect by click");
console.log(error);
});
}
},
mounted() {
// this works well
// this.$ws.connect().catch(error => {
// console.log("could not connect in mounted");
// console.log(error);
// });
}
};
</script>
In the case, I uncomment the mounted hook, after page load I see the console log like this:
websocket tester launched
trying to connect websocket
Opening Web Socket...
Web Socket Opened...
DEPRECATED: undefined is not a recognized STOMP version. In next major client version, this will close the connection.
>>> CONNECT
>>> length 52
<<< CONNECTED
connected to server undefined
got websocket frame:
Frame {command: "CONNECTED", headers: {…}, body: ""}
And everything works correct. But, if I comment the mounted hook and want to connect with the WebSocket by the button click, the console log looks like this:
websocket tester launched
connecting...
trying to connect websocket
Opening Web Socket...
and that's it, the connection isn't established. Why this happens and how to fix it?
OK I figured it out. The problem line was const stompClient = getStompClient("http://localhost:8080/ws"); in the plugin. I've moved it to the connect method and store as ws.object.
if (connected) {
reject("Already connected !");
return;
}
ws.stompClient = getStompClient("http://localhost:8080/ws");
console.log("trying to connect websocket");
ws.stompClient.connect({}, frame => {
Later, I use ws.stompClient and it works fine.

Categories