Giter Club home page Giter Club logo

sockette's Introduction

Sockette

Sockette

The cutest little WebSocket wrapper! ๐Ÿงฆ

Sockette is a tiny (367 bytes) wrapper around WebSocket that will automatically reconnect if the connection is lost!

In addition to attaching additional API methods, Sockette allows you to reuse instances, avoiding the need to redeclare all event listeners.

You have direct access to the (current) underlying WebSocket within every EventListener callback (via event.target).

Install

$ npm install --save sockette

Usage

Unlike WebSocket, you should declare all event listeners on initialization:

const Sockette = require('sockette');

const ws = new Sockette('ws://localhost:3000', {
  timeout: 5e3,
  maxAttempts: 10,
  onopen: e => console.log('Connected!', e),
  onmessage: e => console.log('Received:', e),
  onreconnect: e => console.log('Reconnecting...', e),
  onmaximum: e => console.log('Stop Attempting!', e),
  onclose: e => console.log('Closed!', e),
  onerror: e => console.log('Error:', e)
});

ws.send('Hello, world!');
ws.json({type: 'ping'});
ws.close(); // graceful shutdown

// Reconnect 10s later
setTimeout(ws.reconnect, 10e3);

API

Sockette(url, options)

Returns: Sockette

Returns the Sockette instance.

url

Type: String

The URL you want to connect to โ€” Should be prefixed with ws:// or wss://. This is passed directly to WebSocket.

options.protocols

Type: String|Array

Either a single protocol string or an array of strings used to indicate sub-protocols. See the WebSocket docs for more info.

options.timeout

Type: Number
Default: 1000

The amount of time (in ms) to wait in between reconnection attempts. Defaults to 1 second.

options.maxAttempts

Type: Number
Default: Infinity

The maximum number of attempts to reconnect.

Important: Pass -1 if you want to disable this feature. Although, this is main reason to use Sockette! ๐Ÿ˜‚

options.onopen

Type: Function

The EventListener to run in response to 'open' events. It receives the Event object as its only parameter.

This is called when the connection has been established and is ready to send and receive data.

Important: Sockette will forget the number of previous reconnection attempts, so that the next time connection is lost, you will consistently retry n number of times, as determined by options.maxAttempts.

options.onmessage

Type: Function

The EventListener to run in response to 'message' events. It receives the Event object as its only parameter.

This is called when a message has been received from the server. You'll probably want event.data!

options.onreconnect

Type: Function

The callback to run when attempting to reconnect to the server.

If Sockette is automatically reconnecting in response to an error or unexpected close event, then your onreconnect callback will receive the forwarded Event object.

options.onmaximum

Type: Function

The callback to run when the maxAttempts limit has been met.

This callback will receive the forwarded Event object from onclose.

options.onclose

Type: Function

The EventListener to run in response to 'close' events. It receives the Event object as its only parameter.

This is called when the connection has been closed for any reason.

Important: If the event.code is not 1000, 1001, or 1005 an automatic reconnect attempt will be queued.

options.onerror

Type: Function

The EventListener to run in response to 'error' events. It receives the Event object as its only parameter.

This is called anytime an error occurs.

Important: If the event.code is ECONNREFUSED, an automatic reconnect attempt will be queued.

send(data)

Identical to WebSocket.send(), capable of sending multiple data types.

close(code, reason)

Identical to WebSocket.close().

Note: The code will default to 1000 unless specified.

json(obj)

Convenience method that passes your obj (Object) through JSON.stringify before passing it to WebSocket.send().

reconnect()

If options.maxAttempts has not been exceeded, enqueues a reconnection attempt. Otherwise, it runs your options.onmaximum callback.

open()

Initializes a new WebSocket โ€” used on initialization and by reconnect().

License

MIT ยฉ Luke Edwards

sockette's People

Contributors

gfaugere avatar jdanford avatar kasparlee avatar lukeed avatar maraisr avatar mehmetkose avatar neftaly avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sockette's Issues

Sockette onmessage question

I'm just learning React and using Sockette as one of the first implementations. I managed to get the websocket connection working, however I can't see how I can update a given React State with the received message (onmessage). Sending is working fine and receiving as well, just can't update a given state from outside of the React Component. Below the code:

//Websockets in test.js
import Sockette  from 'sockette';
const ws_scheme = window.location.protocol == "https:" ? "wss" : "ws";
 const ws_path = ws_scheme + '://' + window.location.host + '/ramascene/';
 const ws = new Sockette(ws_path, {
 timeout: 5e3,
 maxAttempts: 10,
 onopen: e => console.log('Connected!', e),
 onmessage: e => console.log('received!', e),
 onreconnect: e => console.log('Reconnecting...', e),
 onmaximum: e => console.log('Stop Attempting!', e),
 onclose: e => console.log('Closed!', e),
 onerror: e => console.log('Error:', e)
 })

.....

//parent component Board also in test.js
class Board extends React.Component<Props, State>{

  handleAjax: Function;
  handleWSSend: Function;
  //#code  ID9
  //default state of variables
   constructor(props) {
      super(props);

      this.handleAjax = this.handleAjax.bind(this)
      //default state
      this.state = {test: "bla"}
    }
    
    //handle the websocket transmission for starting a task
    handleWSSend(){
      console.log("analyse fired")
      ws.send(JSON.stringify({'vizType': "GeoMap",'dimType': "Consumption",
      'action': "start_calc"
     }));
   }
}``

Able to detect network lost?

Hi there, sorry if my issue is silly, I'm still amateur in websockets handling. I'm facing a problem where I couldn't disconnect properly using sockette when the network is offline. I'm currently using sockette to connect with my Websocket API using AWS API Gateway, everything seems fine except when I realized that the connections created by the gateway isn't always being disconnected thus leaving many dead connection records in my DynamoDB. This is how I replicate the issue:

  1. Open new tab and access to my website with websocket connection, wait until it's connected
  2. Turn off my laptop WiFi connection, to simulate offline connection
  3. Close the tab
  4. Turn on my laptop WiFi connection

I'm wondering do Sockette handles such situation, at least have a callback when offline connection is detected? If it's already available, how can I modify my code to cater for that? This is my code in React:

useEffect(
  () => {
    if (isProduction) {
      webSocket = new Sockette(webSocketUrlFor(userId), {
        timeout: 5e3,
        onopen: e => console.log('Connected', e),
        onmessage: onReceivedMessage,
        onreconnect: () => console.log('Reconnecting...'),
        onmaximum: e => console.log('Stop Attempting!', e),
        onclose: e => {
          console.log('Closed connection. Reconnecting...', e);
          webSocket.reconnect();
        },
        onerror: e => console.log('Error:', e)
      });

      return () => {
        webSocket.close();
      };
    }
  },
  [userId]
);

Socket connection code choices

I was wondering on ws.onclose, why on those specific code numbers we donโ€™t want to try to reconnect. Codes 1003, 1001, and 1005. Why not have it try to always reconnect if it loses a connection?

Suggestion for error handler when using send or json

hi, i use json or send on my project, and sometimes i will get an error

Failed to execute 'send' on 'WebSocket': Still in CONNECTING state

i already using handler for when onopen i changed the status which enabling my button can be used and i still sometimes get the same error

so here my suggestion, instead using send(string) or json(data), i think we should be able to add one more param for error lik send(string, errorHandler) or json(data, errorHandler)

How to get error code

How to get error code while getting the error from the socket connection in onerror()?

Still in CONNECTING state

First time I've used sockets in a while...

I'm building a simple react voting example that allows a room of people to click as many times and as fast as they want on one of 6 choices and that will cast their vote.

This definitely seems like an issue with how fast everything can process each vote.

However, I'm not sure where to start?

This is the bulk of the code:

  const onVote = vote => {
    console.log({ vote, ws });
    ws.json({
      action: 'sendMessage',
      data: JSON.stringify(vote)
    });
  };

  const onMessageReceied = ({ data }) => {
    console.log({ data });
    const voteData = JSON.parse(data);
    console.log({ onMessageReceied: voteData });
    setBallotsList({ ...ballotsList, ...voteData });
  };

  useEffect(() => {
    console.log({ ballotsList });
    ws = new Sockette(config.site.api, {
      timeout: 5e3,
      maxAttempts: 1,
      onopen: e => console.log('connected:', e),
      onmessage: e => onMessageReceied(e),
      onreconnect: e => console.log('Reconnecting...', e),
      onmaximum: e => console.log('Stop Attempting!', e),
      onclose: e => console.log('Closed!', e),
      onerror: e => console.log('Error:', e)
    });
    return function cleanup() {
      ws && ws.close();
      ws = null;
    };
  }, [ballotsList]);

project status?

Hi there
I would like hear if this project is still maintained?

Websocket is undefined

Hi, i have a problem when testing my component using mocha & chai, it says:

ReferenceError: WebSocket is not defined
    at module.exports.r.open (/Users/bcw-001/dev/sofia_fe_react/node_modules/sockette/src/index.js:25:32)
    at new module.exports (/Users/bcw-001/dev/sofia_fe_react/node_modules/sockette/src/index.js:48:7)

i use mock-websocket. anyone know what did i miss?

Bind with React and Preact

Hey there.

First of all, thanks for a great work on this library.

So I created a library to bind Sockette to React and Preact at the same time. I wanted to reduce the hassle of switching the component from the two library. the idea just lands in creating a component factory.

You can check it out here.

I was wondering, is there any chance we can merge it with your version of preact-sockette?

This way both React and Preact users can enjoy using this component. and Yes, I am aware of compat libraries :) I just think creating a factory for components is a better way since it can also be used in other alternatives such as Inferno too.

and probably a good idea that all the components that we create for these libraries, be written as factories.

error occurs in IE11 and edge when connection is closed

Environment: React 16.2, webpack 4.10, sockette 2.0.0

in the react lifecycle method componentWillUnmount method, I will close the socket instance , the error occurs ,

the code blow
_20180927181119

error blow
_20180927181225
_20180927181247

when I add annotation to the ws close method , it get ok,
_20180927181606

How can I fix this problem , thx.

Version 2 hides socket

On readme: "Upon creation, the WebSocket is returned directly, exposing the native close and send methods."

But version 2 changed return $.open(); (which returns the ws) to return self; and the websocket is not accessible.

When I close the connection, it doesn't send queryStringParameters

I built up the WebSocket server with AWS API Gateway.

and, I am connecting this with AWS Lambda.

It works well when I connect, but when I disconnect, it doesn't work well.

My React Client Code

import React from 'react';

function socketHandler(uid){
  const wss = new Sockette(`wss://MY_API_GATEWAY_URL.execute-api.ap-northeast-2.amazonaws.com/dev?groupId=GROUP_ID&uid=${uid}`, {
    timeout: 1000,
    maxAttempts: 10,
    onopen: (e: any) => { console.log(e); console.log('Websocket is connected') },
    onmessage: (e: any) => {
      console.log(e.data);
    },
    onclose: (e: any) => { console.log(e); console.log('Websocket is disconnected'); }
  });
  return wss;
}

const SocketForm = (props) => {
  const [socket, setSocket] = React.useState(null);
  
  React.useEffect(()=> {
    setSocket(socketHandler(`MY_UID`);
  }, []);
  const socketDisconnect = () => {
    socket.close();
  }
  return (
    <div> 
      <button onClick={socketDisconnect}>Disconnect</button>
    </div>
  )
}

My Lambda Code

 /* it works well when I connect. */
export const socketHandler = async (evt) => {
  const {groupId, uid} = evt.queryStringParameters; // When I disconnect it occurs ERROR.
 
   /* Skip Saving connectionId */

   return { statusCode: 200, body: JSON.stringify({}) };
};

I'd like to use WebSocket URL with queryParameters even I disconnect.

If I missed something, please reply me.

onerror not returning code

Hello,

The documentation for onerror says "Important: If the event.code is ECONNREFUSED, an automatic reconnect attempt will be queued."

However, when doing onerror: e => console.log('Error:', e), it looks like e.code doesn't exist.

`self` is not necessary

Arrow functions don't create a binding, and a quick look over the code doesn't show a single instance where the difference in bindings would matter. Every instance of this can be replaced with self.

Increment timeout

Can I modify the timeout in onreconnect() -- for example, to increase the delay after 10 attempts to reconnect? I do not see the timeout variable on the event.target.

Testing in Create React App

I built my app starting with the convenient create-react-app. It comes with Jest built in for testing. However, I can't run any tests because of the following error:

ReferenceError: WebSocket is not defined
      
      at Object.<anonymous>.module.exports.r.open (node_modules/sockette/dist/sockette.js:1:508)
      at new Object.<anonymous>.module.exports (node_modules/sockette/dist/sockette.js:1:745)
      at new NTWebSocket (src/server.js:14:15)
      at Object.<anonymous> (src/index.js:22:17)
      at Object.<anonymous> (src/test/App.test.js:21:14)

Re-connection Strategy

Awesome Library.

I was taking a look at the re-connection handler and noticed it just takes a static delay before attempting to reconnect.

I usually like to use some form of re-connection strategy to control how a re-connection occurs for example an Exponential Back-off.

Would this be a suitable feature addition?

To keep the module size down the constructor could take a function:

new Sockette(..., {
  reconnection: (attempts, maxAttempts) => Number
});

SCRIPT5022: SecurityError in IE11

react version:
16.2.0

import the lib:
import Sockette from "sockette";`

get init instance:
2

after the component loaded . then refresh the browser , this error occured :
4

3
1

how can I fix this problem? thanks

Disable reconnect programmatically

Hi, awesome lib.
Is there any way that we can disable reconnect programmatically ?

For example, we init a sockette instance with maxAttempts by default(always enable recconnecting), after a several times of connection failure, I would like to provide a way to disable the further reconnecting manually. Thanks.

Still reconnecting after close()

I just tested v2.0.5 and unfortunately the issue is still there. This is my scenario:

  1. Open WS connection A.
  2. Close WS connection A.
  3. Open WS connection B.
  4. Close WS connection B.
  5. Open WS connection C.

After a while WS connections A and B are reopened. They are initially closed, but re-opened.

[Feature] Ability to set url before reconnecting

Right now in order to change websocket url you have to create a new instance of Sockette. This an issue for us because our url includes authorization token which expires after some time and when Sockette tries to reconnect it tries to reconnect using an expired token.

Here are a couple of possible solutions to this issue:

  1. getUrl config which can be set to a function which either returns a string directly or a Promise<string>. Sockette would use this function every time it tries to automatically establish websocket connection.
  2. setUrl() method on the Sockette class and ability to set onreconnect config to a function which returns a Promise. Sockette would wait for onreconnect promise to finish before it would try to reestablish connection.

@lukeed what do you think about it? Do you have any better suggestions?

Error in v2.0.2 with UglifyJS

When I run our build with v2.0.2 or v2.0.3 I get the following error message. However, if I run with v2.0.1 our project builds without error.

ERROR in 13.ce2f3dc9b0373574d554.chunk.js from UglifyJs
Unexpected token: operator (>) [/work/node_modules/sockette/dist/sockette.js:30,0][13.ce2f3dc9b0373574d554.chunk.js:2646,32]
Child html-webpack-plugin for "index.html":
     1 asset

I have tried updating to the latest html-webpack-plugin in case that was an issue, but it doesn't seem to be.

Why 1005 and ECONNREFUSED

hi,

websocket sometimes is a mystery to me.
Could you please explain why you don't reconnect on error 1005,
and why you reconnect on ECONNREFUSED.

thanks in advance

Force websocket close without reconnection how?

Hi pal,

How do you intentional close the websocket without reconnection execution, its necessary to pass event code to close method?

when manually invoke close method I think that the reconnection should not be done

ws.close()

thanks

onmaximum not triggering

Am I misunderstanding this method or is it not working?

socket = new Sockette(action.url, {
        timeout: 5000,
        maxAttempts: 2,
        onopen: onOpen(store),
        onclose: onClose(store),
        onmessage: onMessage(store),
        onmaximum: onMaximum(store),
        onreconnect: onReconnect(store),
        onerror: noop,
      });

I have this snippet setup. Everything works as expected. When the WS server is down, Sockette tries to connect twice, before giving up, however the onmaximum callback is never triggered.

Heartbeat mechanism to detect connection

Hi pal,
it will be great to have heartbeat mechanism (optional) like ping / pong to check the connection availability, what do you think?

Of course we need special pong message from server (this is why feature must be optional).

Thanks !!!

Specifying the 'binaryType' attribute?

Would a developer be able to specify the binaryType attribute of the websocket?.. such as what's noted in the MDN docs?

Could this be an option or does the developer have access to the native Websocket via sockette?

// Create WebSocket connection.
const socket = new WebSocket('ws://localhost:8080');
socket.binaryType = 'arraybuffer';

ws.close should clear pending setTimeout

If I call ws.close while there's a reconnection setTimeout pending, sockette still tries to reconnect after the timer finishes. I don't think this is the expected behavior, especially when you try to close the websocket after a connection failure, as it keeps trying to reconnect and failing.

Automatically split & re-combine messages over a certain size

Thank you for making this package! It's great.

This is a feature request.

AWS API Gateway allows only a maximum size of 128kb of data to be sent across 4 x 32kb frames when using Websockets:

https://docs.aws.amazon.com/apigateway/latest/developerguide/limits.html

I would love it if this package allowed me to specify the maximum frame size somewhere and then it would automatically split up messages and re-combine them on the other side to overcome this.

TypeError: "Sockette is not a constructor" (Angular/TypeScript)

I've created a new Angular project using the Angular CLI and have installed and attempted to import Sockette into my project (an empty Angular project.)

I am getting the below error when trying to import/require Sockette.

TypeError: "Sockette is not a constructor"
  1. Via import gets me the above error:
import {Component} from '@angular/core';
import {environment} from '../environments/environment';

import * as Sockette from 'sockette';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  constructor() {
    const socket = new Sockette(environment.websocket_server);
  }
}
  1. Via require gets me the same error above:
import {Component} from '@angular/core';
import {environment} from '../environments/environment';

const Sockette = require('sockette');

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  constructor() {
    const socket = new Sockette(environment.websocket_server);
  }
}

When I console.log the Sockette object, I get the following:

import {Component} from '@angular/core';
import {environment} from '../environments/environment';

const Sockette = require('sockette');

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  constructor() {
    console.log(Sockette);
    const socket = new Sockette(environment.websocket_server);
  }
}
Object { default: default(), โ€ฆ }

Which lead me to try the following (which works!)

import {Component} from '@angular/core';
import {environment} from '../environments/environment';

const Sockette = require('sockette');

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  constructor() {
    const socket = new Sockette.default(environment.websocket_server);
  }
}

I'm left assuming this is due to the way Sockette is being exported... any thoughts?

Possible to get WebSocket instance?

Hi, I saw from your README that WebSocket object is available in each EventListener, but is there a way to access it outside of event listeners? Would like to get the state of WebSocket to determine whether to stop an interval to ping the websocket server, thanks.

Is there a way to tell if reconnection attempts are over?

Hi! I loved your lib right away!

I have a question, is there a way to tell if max attempts are reached and it will no longer reconnect? Something like ws.isExhausted or ws.doneTrying? We have HTTP failover in our apps and I would like to only failover after Sockette is exhausted.

If there isn't such a flag I'd be glad to PR.

Cheers

Ability to add custom headers?

I don't see any option to add custom headers to the WS connection. I know this may not be used for browser based implementations of websocket connections, but many server-side client libs need to provide an Authorization header to connect to a websocket. Is this something you could see using on this project? Thanks!

Access underlying socket object

In an application I'm working on I'd like to check that the socket has flushed data. This can be done using socket.bufferedAmount according to this SO post

Could this library support a function to check this, or simply expose the underlying socket object for these use cases, e.g:

const ws = new Sockette('ws://localhost:3000', {
  timeout: 5e3,
  maxAttempts: 10,
  onopen: e => console.log('Connected!', e),
  onmessage: e => console.log('Received:', e),
  onreconnect: e => console.log('Reconnecting...', e),
  onmaximum: e => console.log('Stop Attempting!', e),
  onclose: e => console.log('Closed!', e),
  onerror: e => console.log('Error:', e)
});

// access underlying socket
ws.socket.bufferedAmount

Updating npm

Hello there,

It looks like the latest release on npm is not including your typings for typescript.
Do you mind publishing a new minor version with those great changes?
Thank you!

Reconnections are not being queued.

Basically the opposite of #23, onmaximum triggers immediately. I have my Sockette instances configured to attempt to connect 5 times before giving up. If my backend server is not running, it attempts one connection, fails, and gives up. I can confirm that if the server is running and it successfully connects, then the server is shut down, it will attempt one reconnect before failing and giving up again.

After inspecting the events, I'm not getting a 1000 or 1005. In fact, the only event code I'm able to actually see is 1006, which should trigger a reconnect according to the docs. What's happening is a connection attempt is made, fails, then calls onerror and onclose (which is expected), then straight to onmaximum.

image

Here's the code currently (with logging stuff removed):

this._ws = new Sockette(url, {
  timeout: 60000,
  maxAttempts: 5,
  onopen: () => {
    console.log('[Chat] Connection successful.')
    this.setState({ connected: true }, () => {
      const payload = {
        channel: 'chat-login',
        payload: { from: this.state.myself }
      }
      this._ws.json(payload)
    })
  },
  onclose: () => console.log('[Chat] Connection closed.'),
  onmessage: ({ data }) => this._onMessage(JSON.parse(data)),
  onmaximum: () => console.error('[Chat] Too many connection attempts. Giving up.'),
  onreconnect: () => console.log('[Chat] Reconnecting...'),
  onerror: () => {
    console.error('[Chat] Disconnected.')
    this.setState({ connected: false })
  }
})

Shouldn't it attempt to connect four more times, or have I misread or missed something in the documentation?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.