Home

Awesome

websocket-as-promised

<img alt="websocket-as-promised logo" align="right" src="https://user-images.githubusercontent.com/1473072/32486445-b2443538-c3b7-11e7-8e9f-94c95efad760.png"/>

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

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

<dl> <dt><a href="#WebSocketAsPromised">WebSocketAsPromised</a></dt> <dd></dd> </dl>

Typedefs

<dl> <dt><a href="#Options">Options</a> : <code>Object</code></dt> <dd></dd> </dl>

<a name="WebSocketAsPromised"></a>

WebSocketAsPromised

Kind: global class

<a name="new_WebSocketAsPromised_new"></a>

new WebSocketAsPromised(url, [options])

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

ParamTypeDescription
url<code>String</code>WebSocket URL
[options]<code>Options</code>

<a name="WebSocketAsPromised+ws"></a>

wsp.ws ⇒ <code>WebSocket</code>

Returns original WebSocket instance created by options.createWebSocket.

Kind: instance property of <code>WebSocketAsPromised</code>
<a name="WebSocketAsPromised+url"></a>

wsp.url ⇒ <code>String</code>

Returns WebSocket url.

Kind: instance property of <code>WebSocketAsPromised</code>
<a name="WebSocketAsPromised+isOpening"></a>

wsp.isOpening ⇒ <code>Boolean</code>

Is WebSocket connection in opening state.

Kind: instance property of <code>WebSocketAsPromised</code>
<a name="WebSocketAsPromised+isOpened"></a>

wsp.isOpened ⇒ <code>Boolean</code>

Is WebSocket connection opened.

Kind: instance property of <code>WebSocketAsPromised</code>
<a name="WebSocketAsPromised+isClosing"></a>

wsp.isClosing ⇒ <code>Boolean</code>

Is WebSocket connection in closing state.

Kind: instance property of <code>WebSocketAsPromised</code>
<a name="WebSocketAsPromised+isClosed"></a>

wsp.isClosed ⇒ <code>Boolean</code>

Is WebSocket connection closed.

Kind: instance property of <code>WebSocketAsPromised</code>
<a name="WebSocketAsPromised+onOpen"></a>

wsp.onOpen ⇒ <code>Channel</code>

Event channel triggered when connection is opened.

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

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

<a name="WebSocketAsPromised+onSend"></a>

wsp.onSend ⇒ <code>Channel</code>

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

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

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

<a name="WebSocketAsPromised+onMessage"></a>

wsp.onMessage ⇒ <code>Channel</code>

Event channel triggered every time when message received from server.

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

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

<a name="WebSocketAsPromised+onUnpackedMessage"></a>

wsp.onUnpackedMessage ⇒ <code>Channel</code>

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 <code>WebSocketAsPromised</code>
See: https://vitalets.github.io/chnl/#channel
Example

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

<a name="WebSocketAsPromised+onResponse"></a>

wsp.onResponse ⇒ <code>Channel</code>

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 <code>WebSocketAsPromised</code>
See: https://vitalets.github.io/chnl/#channel
Example

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

<a name="WebSocketAsPromised+onClose"></a>

wsp.onClose ⇒ <code>Channel</code>

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

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

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

<a name="WebSocketAsPromised+onError"></a>

wsp.onError ⇒ <code>Channel</code>

Event channel triggered when by Websocket 'error' event.

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

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

<a name="WebSocketAsPromised+open"></a>

wsp.open() ⇒ <code>Promise.<Event></code>

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

Kind: instance method of <code>WebSocketAsPromised</code>
<a name="WebSocketAsPromised+sendRequest"></a>

wsp.sendRequest(data, [options]) ⇒ <code>Promise</code>

Performs request and waits for response.

Kind: instance method of <code>WebSocketAsPromised</code>

ParamTypeDefault
data<code>*</code>
[options]<code>Object</code>
[options.requestId]<code>String</code> | <code>Number</code><code><auto-generated></code>
[options.timeout]<code>Number</code><code>0</code>

<a name="WebSocketAsPromised+sendPacked"></a>

wsp.sendPacked(data)

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

Kind: instance method of <code>WebSocketAsPromised</code>

ParamType
data<code>*</code>

<a name="WebSocketAsPromised+send"></a>

wsp.send(data)

Sends data without packing.

Kind: instance method of <code>WebSocketAsPromised</code>

ParamType
data<code>String</code> | <code>Blob</code> | <code>ArrayBuffer</code>

<a name="WebSocketAsPromised+waitUnpackedMessage"></a>

wsp.waitUnpackedMessage(predicate, [options]) ⇒ <code>Promise</code>

Waits for particular message to come.

Kind: instance method of <code>WebSocketAsPromised</code>

ParamTypeDefaultDescription
predicate<code>function</code>function to check incoming message.
[options]<code>Object</code>
[options.timeout]<code>Number</code><code>0</code>
[options.timeoutError]<code>Error</code>

Example

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

<a name="WebSocketAsPromised+close"></a>

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

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

Kind: instance method of <code>WebSocketAsPromised</code>

ParamTypeDefaultDescription
[code]<code>number</code><code>1000</code>A numeric value indicating the status code.
[reason]<code>string</code>A human-readable reason for closing connection.

<a name="WebSocketAsPromised+removeAllListeners"></a>

wsp.removeAllListeners()

Removes all listeners from WSP instance. Useful for cleanup.

Kind: instance method of <code>WebSocketAsPromised</code>
<a name="Options"></a>

Options : <code>Object</code>

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

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

Changelog

Please see CHANGELOG.md.

License

MIT @ Vitaliy Potapov

<div align="center"> * * *<br> <i>If you love :heart: JavaScript and would like to track new trending repositories, <br> have a look on <a href="https://github.com/vitalets/github-trending-repos">vitalets/github-trending-repos</a>.</i> </div>