Skip to content

vitalets/websocket-as-promised

Repository files navigation

websocket-as-promised

websocket-as-promised logo

Actions Status Known Vulnerabilities npm license

A WebSocket client library with Promise-based API for browser and Node.js.

Example

import WebSocketAsPromised from 'websocket-as-promised';

// create instance of WebSocket connection
const wsp = new WebSocketAsPromised('ws://example.com');

// wait for WebSocket connection to open
await wsp.open();

// send some data
wsp.send('data');

// wait for connection to close
await wsp.close();

Contents

Requirements

  • global Promise constructor

Installation

npm i websocket-as-promised --save

Usage in browser

import WebSocketAsPromised from 'websocket-as-promised';

const wsp = new WebSocketAsPromised('ws://example.com');

wsp.open()
  .then(() => wsp.send('message'))
  .then(() => wsp.close())
  .catch(e => console.error(e));

Or with ES7 async / await:

import WebSocketAsPromised from 'websocket-as-promised';

const wsp = new WebSocketAsPromised('ws://example.com');

(async () => {
  try {
    await wsp.open();
    wsp.send('message');
  } catch(e) {
    console.error(e);
  } finally {
    await wsp.close();
  }
})();

Usage in Node.js

As there is no built-in WebSocket client in Node.js, you should use a third-party WebSocket npm package.

Usage with websocket

Here you should use W3C compatible client - W3CWebSocket:

const WebSocketAsPromised = require('websocket-as-promised');
const W3CWebSocket = require('websocket').w3cwebsocket;

const wsp = new WebSocketAsPromised('ws://example.com', {
  createWebSocket: url => new W3CWebSocket(url)
});

wsp.open()
  .then(() => wsp.send('message'))
  .then(() => wsp.close())
  .catch(e => console.error(e));

Usage with ws

Here it is important to define extractMessageData option as event data are passed directly to onmessage handler, not as event.data by spec:

const WebSocketAsPromised = require('websocket-as-promised');
const WebSocket = require('ws');

const wsp = new WebSocketAsPromised('ws://example.com', {
  createWebSocket: url => new WebSocket(url),
  extractMessageData: event => event, // <- this is important
});

wsp.open()
  .then(() => wsp.send('message'))
  .then(() => wsp.close())
  .catch(e => console.error(e));

Sending raw data

To send raw data use .send() method:

wsp.send('foo');

To handle raw data from server use .onMessage channel:

wsp.onMessage.addListener(data => console.log(data));

Sending JSON

To send JSON you should define packMessage / unpackMessage options:

const wsp = new WebSocketAsPromised(wsUrl, {
  packMessage: data => JSON.stringify(data),
  unpackMessage: data => JSON.parse(data)
});

To send data use .sendPacked() method passing json as parameter:

wsp.sendPacked({foo: 'bar'});

To read unpacked data from received message you can subscribe to onUnpackedMessage channel:

wsp.onUnpackedMessage.addListener(data => console.log(data.status));

Sending binary

Example of sending Uint8Array:

const wsp = new WebSocketAsPromised(wsUrl, {
    packMessage: data => (new Uint8Array(data)).buffer,
    unpackMessage: data => new Uint8Array(data),
});

wsp.open()
  .then(() => wsp.sendPacked([1, 2, 3]))
  .then(() => wsp.close())
  .catch(e => console.error(e));

Sending requests

websocket-as-promised provides simple request-response mechanism (JSON RPC). Method .sendRequest() sends message with unique requestId and returns promise. That promise get resolved when response message with the same requestId comes. For reading/setting requestId from/to message there are two functions defined in options attachRequestId / extractRequestId:

const wsp = new WebSocketAsPromised(wsUrl, {
  packMessage: data => JSON.stringify(data),
  unpackMessage: data => JSON.parse(data),
  attachRequestId: (data, requestId) => Object.assign({id: requestId}, data), // attach requestId to message as `id` field
  extractRequestId: data => data && data.id,                                  // read requestId from message `id` field
});

wsp.open()
 .then(() => wsp.sendRequest({foo: 'bar'})) // actually sends {foo: 'bar', id: 'xxx'}, because `attachRequestId` defined above
 .then(response => console.log(response));  // waits server message with corresponding requestId: {id: 'xxx', ...}

By default requestId value is auto-generated, but you can set it manually:

wsp.sendRequest({foo: 'bar'}, {requestId: 42});

Note: you should implement yourself attaching requestId on server side.

API

Classes

WebSocketAsPromised

Typedefs

Options : Object

WebSocketAsPromised

Kind: global class

new WebSocketAsPromised(url, [options])

Constructor. Unlike original WebSocket it does not immediately open connection. Please call open() method to connect.

Param Type Description
url String WebSocket URL
[options] Options

wsp.ws ⇒ WebSocket

Returns original WebSocket instance created by options.createWebSocket.

Kind: instance property of WebSocketAsPromised

wsp.url ⇒ String

Returns WebSocket url.

Kind: instance property of WebSocketAsPromised

wsp.isOpening ⇒ Boolean

Is WebSocket connection in opening state.

Kind: instance property of WebSocketAsPromised

wsp.isOpened ⇒ Boolean

Is WebSocket connection opened.

Kind: instance property of WebSocketAsPromised

wsp.isClosing ⇒ Boolean

Is WebSocket connection in closing state.

Kind: instance property of WebSocketAsPromised

wsp.isClosed ⇒ Boolean

Is WebSocket connection closed.

Kind: instance property of WebSocketAsPromised

wsp.onOpen ⇒ Channel

Event channel triggered when connection is opened.

Kind: instance property of WebSocketAsPromised
See: https://vitalets.github.io/chnl/#channel
Example

wsp.onOpen.addListener(() => console.log('Connection opened'));

wsp.onSend ⇒ Channel

Event channel triggered every time when message is sent to server.

Kind: instance property of WebSocketAsPromised
See: https://vitalets.github.io/chnl/#channel
Example

wsp.onSend.addListener(data => console.log('Message sent', data));

wsp.onMessage ⇒ Channel

Event channel triggered every time when message received from server.

Kind: instance property of WebSocketAsPromised
See: https://vitalets.github.io/chnl/#channel
Example

wsp.onMessage.addListener(message => console.log(message));

wsp.onUnpackedMessage ⇒ Channel

Event channel triggered every time when received message is successfully unpacked. For example, if you are using JSON transport, the listener will receive already JSON parsed data.

Kind: instance property of WebSocketAsPromised
See: https://vitalets.github.io/chnl/#channel
Example

wsp.onUnpackedMessage.addListener(data => console.log(data.foo));

wsp.onResponse ⇒ Channel

Event channel triggered every time when response to some request comes. Received message considered a response if requestId is found in it.

Kind: instance property of WebSocketAsPromised
See: https://vitalets.github.io/chnl/#channel
Example

wsp.onResponse.addListener(data => console.log(data));

wsp.onClose ⇒ Channel

Event channel triggered when connection closed. Listener accepts single argument {code, reason}.

Kind: instance property of WebSocketAsPromised
See: https://vitalets.github.io/chnl/#channel
Example

wsp.onClose.addListener(event => console.log(`Connections closed: ${event.reason}`));

wsp.onError ⇒ Channel

Event channel triggered when by Websocket 'error' event.

Kind: instance property of WebSocketAsPromised
See: https://vitalets.github.io/chnl/#channel
Example

wsp.onError.addListener(event => console.error(event));

wsp.open() ⇒ Promise.<Event>

Opens WebSocket connection. If connection already opened, promise will be resolved with "open event".

Kind: instance method of WebSocketAsPromised

wsp.sendRequest(data, [options]) ⇒ Promise

Performs request and waits for response.

Kind: instance method of WebSocketAsPromised

Param Type Default
data *
[options] Object
[options.requestId] String | Number <auto-generated>
[options.timeout] Number 0

wsp.sendPacked(data)

Packs data with options.packMessage and sends to the server.

Kind: instance method of WebSocketAsPromised

Param Type
data *

wsp.send(data)

Sends data without packing.

Kind: instance method of WebSocketAsPromised

Param Type
data String | Blob | ArrayBuffer

wsp.waitUnpackedMessage(predicate, [options]) ⇒ Promise

Waits for particular message to come.

Kind: instance method of WebSocketAsPromised

Param Type Default Description
predicate function function to check incoming message.
[options] Object
[options.timeout] Number 0
[options.timeoutError] Error

Example

const response = await wsp.waitUnpackedMessage(data => data && data.foo === 'bar');

wsp.close([code], [reason]) ⇒ Promise.<Event>

Closes WebSocket connection. If connection already closed, promise will be resolved with "close event".

Kind: instance method of WebSocketAsPromised

Param Type Default Description
[code] number 1000 A numeric value indicating the status code.
[reason] string A human-readable reason for closing connection.

wsp.removeAllListeners()

Removes all listeners from WSP instance. Useful for cleanup.

Kind: instance method of WebSocketAsPromised

Options : Object

Kind: global typedef
Defaults: please see options.js
Properties

Name Type Default Description
[createWebSocket] function url => new WebSocket(url) custom function for WebSocket construction.
[packMessage] function noop packs message for sending. For example, data => JSON.stringify(data).
[unpackMessage] function noop unpacks received message. For example, data => JSON.parse(data).
[attachRequestId] function noop injects request id into data. For example, (data, requestId) => Object.assign({requestId}, data).
[extractRequestId] function noop extracts request id from received data. For example, data => data.requestId.
[extractMessageData] function event => event.data extracts data from event object.
timeout Number 0 timeout for opening connection and sending messages.
connectionTimeout Number 0 special timeout for opening connection, by default equals to timeout.

Changelog

Please see CHANGELOG.md.

License

MIT @ Vitaliy Potapov

* * *
If you love ❤️ JavaScript and would like to track new trending repositories,
have a look on vitalets/github-trending-repos.