Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/vitalets/websocket-as-promised
A Promise-based API for WebSockets
https://github.com/vitalets/websocket-as-promised
javascript nodejs promise websocket websocket-api websocket-client
Last synced: about 8 hours ago
JSON representation
A Promise-based API for WebSockets
- Host: GitHub
- URL: https://github.com/vitalets/websocket-as-promised
- Owner: vitalets
- License: mit
- Created: 2017-06-23T14:54:23.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2024-09-25T12:52:36.000Z (3 months ago)
- Last Synced: 2024-12-04T23:51:38.832Z (7 days ago)
- Topics: javascript, nodejs, promise, websocket, websocket-api, websocket-client
- Language: JavaScript
- Homepage:
- Size: 794 KB
- Stars: 595
- Watchers: 11
- Forks: 42
- Open Issues: 7
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
- awesome-list - websocket-as-promised - based API for WebSockets | vitalets | 511 | (JavaScript)
- my-awesome-list - websocket-as-promised - based API for WebSockets | vitalets | 596 | (JavaScript)
README
# websocket-as-promised
[![Actions Status](https://github.com/vitalets/websocket-as-promised/workflows/autotests/badge.svg)](https://github.com/vitalets/websocket-as-promised/actions)
[![Known Vulnerabilities](https://snyk.io/test/github/vitalets/websocket-as-promised/badge.svg?targetFile=package.json)](https://snyk.io/test/github/vitalets/websocket-as-promised?targetFile=package.json)
[![npm](https://img.shields.io/npm/v/websocket-as-promised.svg)](https://www.npmjs.com/package/websocket-as-promised)
[![license](https://img.shields.io/npm/l/websocket-as-promised.svg)](https://www.npmjs.com/package/websocket-as-promised)A [WebSocket] client library with [Promise]-based API for browser and Node.js.
## Example
```js
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](#requirements)
* [Installation](#installation)
* [Usage](#usage-in-browser)
* [Browser](#usage-in-browser)
* [Node.js](#usage-in-nodejs)
* [Sending data](#sending-raw-data)
* [raw](#sending-raw-data)
* [JSON](#sending-json)
* [binary](#sending-binary)
* [request / response](#sending-requests)
* [API](#api)
* [Changelog](#changelog)
* [License](#license)## Requirements
* global `Promise` constructor## Installation
```bash
npm i websocket-as-promised --save
```## Usage in browser
```js
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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function):
```js
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](https://www.npmjs.com/package/websocket)
Here you should use W3C compatible client - [W3CWebSocket](https://github.com/theturtle32/WebSocket-Node/blob/master/docs/W3CWebSocket.md):
```js
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](https://www.npmjs.com/package/ws)
Here it is important to define `extractMessageData` option as event data are passed directly to `onmessage` handler,
not as `event.data` by [spec](https://html.spec.whatwg.org/multipage/comms.html#dom-messageevent-data):
```js
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:
```js
wsp.send('foo');
```
To handle raw data from server use `.onMessage` channel:
```js
wsp.onMessage.addListener(data => console.log(data));
```## Sending JSON
To send JSON you should define `packMessage / unpackMessage` options:
```js
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:
```js
wsp.sendPacked({foo: 'bar'});
```
To read unpacked data from received message you can subscribe to `onUnpackedMessage` channel:
```js
wsp.onUnpackedMessage.addListener(data => console.log(data.status));
```## Sending binary
Example of sending `Uint8Array`:
```js
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](https://www.jsonrpc.org)).
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`:
```js
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:
```js
wsp.sendRequest({foo: 'bar'}, {requestId: 42});
```> Note: you should implement yourself attaching `requestId` on server side.
## API
### Classes
### Typedefs
-
Options :Object
### WebSocketAsPromised
**Kind**: global class
* [WebSocketAsPromised](#WebSocketAsPromised)
* [new WebSocketAsPromised(url, [options])](#new_WebSocketAsPromised_new)
* [.ws](#WebSocketAsPromised+ws) ⇒ WebSocket
* [.url](#WebSocketAsPromised+url) ⇒ String
* [.isOpening](#WebSocketAsPromised+isOpening) ⇒ Boolean
* [.isOpened](#WebSocketAsPromised+isOpened) ⇒ Boolean
* [.isClosing](#WebSocketAsPromised+isClosing) ⇒ Boolean
* [.isClosed](#WebSocketAsPromised+isClosed) ⇒ Boolean
* [.onOpen](#WebSocketAsPromised+onOpen) ⇒ Channel
* [.onSend](#WebSocketAsPromised+onSend) ⇒ Channel
* [.onMessage](#WebSocketAsPromised+onMessage) ⇒ Channel
* [.onUnpackedMessage](#WebSocketAsPromised+onUnpackedMessage) ⇒ Channel
* [.onResponse](#WebSocketAsPromised+onResponse) ⇒ Channel
* [.onClose](#WebSocketAsPromised+onClose) ⇒ Channel
* [.onError](#WebSocketAsPromised+onError) ⇒ Channel
* [.open()](#WebSocketAsPromised+open) ⇒ Promise.<Event>
* [.sendRequest(data, [options])](#WebSocketAsPromised+sendRequest) ⇒ Promise
* [.sendPacked(data)](#WebSocketAsPromised+sendPacked)
* [.send(data)](#WebSocketAsPromised+send)
* [.waitUnpackedMessage(predicate, [options])](#WebSocketAsPromised+waitUnpackedMessage) ⇒ Promise
* [.close([code], [reason])](#WebSocketAsPromised+close) ⇒ Promise.<Event>
* [.removeAllListeners()](#WebSocketAsPromised+removeAllListeners)
#### 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
](#Options) | |
#### wsp.ws ⇒ WebSocket
Returns original WebSocket instance created by `options.createWebSocket`.
**Kind**: instance property of [WebSocketAsPromised
](#WebSocketAsPromised)
#### wsp.url ⇒ String
Returns WebSocket url.
**Kind**: instance property of [WebSocketAsPromised
](#WebSocketAsPromised)
#### wsp.isOpening ⇒ Boolean
Is WebSocket connection in opening state.
**Kind**: instance property of [WebSocketAsPromised
](#WebSocketAsPromised)
#### wsp.isOpened ⇒ Boolean
Is WebSocket connection opened.
**Kind**: instance property of [WebSocketAsPromised
](#WebSocketAsPromised)
#### wsp.isClosing ⇒ Boolean
Is WebSocket connection in closing state.
**Kind**: instance property of [WebSocketAsPromised
](#WebSocketAsPromised)
#### wsp.isClosed ⇒ Boolean
Is WebSocket connection closed.
**Kind**: instance property of [WebSocketAsPromised
](#WebSocketAsPromised)
#### wsp.onOpen ⇒ Channel
Event channel triggered when connection is opened.
**Kind**: instance property of [WebSocketAsPromised
](#WebSocketAsPromised)
**See**: https://vitalets.github.io/chnl/#channel
**Example**
```js
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
](#WebSocketAsPromised)
**See**: https://vitalets.github.io/chnl/#channel
**Example**
```js
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
](#WebSocketAsPromised)
**See**: https://vitalets.github.io/chnl/#channel
**Example**
```js
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
](#WebSocketAsPromised)
**See**: https://vitalets.github.io/chnl/#channel
**Example**
```js
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
](#WebSocketAsPromised)
**See**: https://vitalets.github.io/chnl/#channel
**Example**
```js
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
](#WebSocketAsPromised)
**See**: https://vitalets.github.io/chnl/#channel
**Example**
```js
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
](#WebSocketAsPromised)
**See**: https://vitalets.github.io/chnl/#channel
**Example**
```js
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
](#WebSocketAsPromised)
#### wsp.sendRequest(data, [options]) ⇒ Promise
Performs request and waits for response.
**Kind**: instance method of [WebSocketAsPromised
](#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
](#WebSocketAsPromised)
| Param | Type |
| --- | --- |
| data | \*
|
#### wsp.send(data)
Sends data without packing.
**Kind**: instance method of [WebSocketAsPromised
](#WebSocketAsPromised)
| Param | Type |
| --- | --- |
| data | String
\| Blob
\| ArrayBuffer
|
#### wsp.waitUnpackedMessage(predicate, [options]) ⇒ Promise
Waits for particular message to come.
**Kind**: instance method of [WebSocketAsPromised
](#WebSocketAsPromised)
| Param | Type | Default | Description |
| --- | --- | --- | --- |
| predicate | function
| | function to check incoming message. |
| [options] | Object
| | |
| [options.timeout] | Number
| 0
| |
| [options.timeoutError] | Error
| | |
**Example**
```js
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
](#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
](#WebSocketAsPromised)
### Options : Object
**Kind**: global typedef
**Defaults**: please see [options.js](https://github.com/vitalets/websocket-as-promised/blob/master/src/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](CHANGELOG.md).
## License
MIT @ [Vitaliy Potapov](https://github.com/vitalets)
* * *
If you love :heart: JavaScript and would like to track new trending repositories,
have a look on vitalets/github-trending-repos.
[Promise]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise
[WebSocket]: https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API