├── .babelrc ├── .gitignore ├── .npmignore ├── src ├── index.js ├── error.js └── main.js ├── test ├── helper.js ├── exports.js ├── timeout.js ├── request_response.js ├── disconnect.js ├── error.js └── request_response_error.js ├── sample ├── server.js ├── client.js └── server-with-middleware.js ├── .circleci └── config.yml ├── .eslintrc.json ├── package.json └── README.md /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ "es2015", "stage-0" ] 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *#* 3 | .DS_Store 4 | node_modules/ 5 | *.log 6 | *.log.* 7 | lib/ 8 | tmp/ 9 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | test/ 3 | samples/ 4 | tmp/ 5 | package-lock.json 6 | circle.yml 7 | .babelrc 8 | .eslintrc.json 9 | *.log 10 | *.log.* 11 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import SocketIORequest from './main' 2 | import {TimeoutError, SocketIOError} from './error' 3 | 4 | module.exports = (io, options) => new SocketIORequest(io, options) 5 | Object.assign(module.exports, {TimeoutError, SocketIOError}) 6 | -------------------------------------------------------------------------------- /test/helper.js: -------------------------------------------------------------------------------- 1 | import SocketIO from 'socket.io' 2 | 3 | export const delay = (msec) => new Promise(resolve => setTimeout(resolve, msec)) 4 | 5 | export const port = (process.env.PORT || 3000) - 0 6 | 7 | var server = null 8 | export function Server () { 9 | return server || (server = SocketIO(port)) 10 | } 11 | -------------------------------------------------------------------------------- /sample/server.js: -------------------------------------------------------------------------------- 1 | var ioreq = require('../') 2 | // var ioreq = require('socket.io-request') 3 | 4 | var io = require('socket.io')(3000) 5 | 6 | io.on('connection', function (socket) { 7 | console.log('new client! ' + socket.id) 8 | 9 | ioreq(socket).response('toUpper', function (req, res) { 10 | console.log(req) 11 | res(req.toUpperCase()) 12 | }) 13 | }) 14 | -------------------------------------------------------------------------------- /test/exports.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 3 | import {assert} from 'chai' 4 | 5 | import ioreq, {TimeoutError, SocketIOError} from '../' 6 | 7 | describe('npm exports', function () { 8 | it('should export function', function () { 9 | assert.isFunction(ioreq) 10 | }) 11 | 12 | it('should export errors', function () { 13 | assert.isFunction(TimeoutError) 14 | assert.isFunction(SocketIOError) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | - image: circleci/node:10.4.0 6 | working_directory: ~/app 7 | steps: 8 | - run: 'node -v' 9 | - run: 'npm -v' 10 | - checkout 11 | - run: 'npm ci' 12 | - run: 'npm run build' 13 | - run: 14 | command: 'npm run test:standard' 15 | when: always 16 | - run: 17 | command: 'npm run test:mocha' 18 | when: always 19 | -------------------------------------------------------------------------------- /sample/client.js: -------------------------------------------------------------------------------- 1 | var ioreq = require('../') 2 | // var ioreq = require('socket.io-request') 3 | 4 | var io = require('socket.io-client')('http://localhost:3000') 5 | 6 | io.on('connect', () => console.log('connect!')) 7 | io.on('disconnect', () => console.log('disconnect!')) 8 | 9 | io.once('connect', function () { 10 | process.stdin.on('data', async function (data) { 11 | try { 12 | const res = await ioreq(io).request('toUpper', data.toString().trim()) 13 | console.log(res) 14 | } catch (err) { 15 | console.error(err.stack || err) 16 | } 17 | }) 18 | }) 19 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["eslint:recommended"], 3 | "parser": "babel-eslint", 4 | "env":{ 5 | "node": true, 6 | "browser": true, 7 | "es6": true 8 | }, 9 | "plugins":[ 10 | ], 11 | "rules":{ 12 | "strict": [2, "global"], 13 | "semi": 2, 14 | "new-cap": 0, 15 | "comma-spacing": [2, {"before": false, "after": true}], 16 | "no-unused-vars": [1, {"args": "none"}], 17 | "no-constant-condition": 0, 18 | "no-shadow": 0, 19 | "no-loop-func": 0, 20 | "curly": 0, 21 | "no-constant-condition": 1, 22 | "no-console": 1 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /sample/server-with-middleware.js: -------------------------------------------------------------------------------- 1 | var ioreq = require('../') 2 | // var ioreq = require('socket.io-request') 3 | 4 | var io = require('socket.io')(3000) 5 | 6 | async function logger (req, res, next) { 7 | console.log('received', req) 8 | const result = await next() 9 | console.log('returned', result) 10 | } 11 | 12 | function validator (req, res, next) { 13 | try { 14 | if (!(/^[a-z]+$/.test(req))) { 15 | throw new Error('request must be lower case alphabet.') 16 | } 17 | } catch (err) { 18 | res.error(err) 19 | return err 20 | } 21 | return next() 22 | } 23 | 24 | async function upper (req, res) { 25 | const result = req.toUpperCase() 26 | res(result) 27 | return result 28 | } 29 | 30 | io.on('connection', function (socket) { 31 | console.log('new client! ' + socket.id) 32 | 33 | ioreq(socket).response('toUpper', logger, validator, upper) 34 | }) 35 | -------------------------------------------------------------------------------- /test/timeout.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 3 | import {assert} from 'chai' 4 | import {Server, port, delay} from './helper' 5 | 6 | import Client from 'socket.io-client' 7 | 8 | import ioreq, {TimeoutError} from '../src/' 9 | 10 | const server = Server() 11 | 12 | describe('timeout option', function () { 13 | it('should timeout in 1 sec', function (done) { 14 | this.timeout(2000) 15 | server.on('connection', (socket) => { 16 | ioreq(socket).response('timeout', async (req, res) => { 17 | await delay(1500) 18 | res('done') 19 | }) 20 | }) 21 | 22 | const client = Client(`http://localhost:${port}`) 23 | client.once('connect', async () => { 24 | let err, res 25 | try { 26 | res = await ioreq(client, {timeout: 1000}).request('timeout') 27 | } catch (_err) { 28 | err = _err 29 | } 30 | assert.isUndefined(res) 31 | assert.equal(err.name, TimeoutError.name) 32 | done() 33 | }) 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /src/error.js: -------------------------------------------------------------------------------- 1 | import serializeError from 'serialize-error' 2 | import deserializeError from 'deserialize-error' 3 | 4 | function serializeErrorWithoutStack (err) { 5 | delete err.stack 6 | return serializeError(err) 7 | } 8 | 9 | // convert (nested) Error object to Plain object to send via socket.io 10 | export function convertErrorToObject (err) { 11 | if (err instanceof Error) return serializeErrorWithoutStack(err) 12 | if (err instanceof Array) return err.map(serializeErrorWithoutStack) 13 | let obj = {} 14 | for (let k in err) { 15 | if (err.hasOwnProperty(k)) { 16 | obj[k] = serializeErrorWithoutStack(err[k]) 17 | } 18 | } 19 | return obj 20 | } 21 | 22 | // convert nested object to Error 23 | export function convertObjectToError (obj) { 24 | if (obj instanceof Error) return obj 25 | if (obj instanceof Array) return obj.map(deserializeError) 26 | if (typeof obj !== 'object') return obj 27 | let err = deserializeError(obj) 28 | if (err !== obj) return err 29 | err = {} 30 | for (let k in obj) { 31 | err[k] = deserializeError(obj[k]) 32 | } 33 | return err 34 | } 35 | 36 | export class TimeoutError extends Error { 37 | constructor (message) { 38 | super(message) 39 | this.name = 'TimeoutError' 40 | } 41 | } 42 | 43 | export class SocketIOError extends Error { 44 | constructor (message) { 45 | super(message) 46 | this.name = 'SocketIOError' 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /test/request_response.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 3 | import {assert} from 'chai' 4 | import {Server, port} from './helper' 5 | 6 | import Client from 'socket.io-client' 7 | 8 | import ioreq from '../src/' 9 | 10 | const server = Server() 11 | 12 | describe('request-response', function () { 13 | describe('from Client to Server', function () { 14 | it('should respond uppercase string', function (done) { 15 | server.on('connection', (socket) => { 16 | ioreq(socket).response('toUpper', (req, res) => { 17 | res(req.str.toUpperCase()) 18 | }) 19 | }) 20 | 21 | const client = Client(`http://localhost:${port}`) 22 | client.once('connect', async () => { 23 | const str = await ioreq(client).request('toUpper', {str: 'hello'}) 24 | assert.equal(str, 'HELLO') 25 | done() 26 | }) 27 | }) 28 | }) 29 | 30 | describe('from Server to Client', function () { 31 | it('should respond sum of array', function (done) { 32 | const client = Client(`http://localhost:${port}`) 33 | client.once('connect', function () { 34 | ioreq(client).response('sum', (req, res) => { 35 | res(req.reduce((a, b) => a + b)) 36 | }) 37 | }) 38 | 39 | server.on('connection', async (socket) => { 40 | const sum = await ioreq(socket).request('sum', [8, 9, 10]) 41 | assert.equal(sum, 27) 42 | done() 43 | }) 44 | }) 45 | }) 46 | }) 47 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "socket.io-request", 3 | "version": "0.8.0", 4 | "description": "bidirectional request-response for socket.io", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "test": "run-s test:*", 8 | "test:mocha": "mocha test/*.js -r babel-polyfill --compilers js:babel-register", 9 | "test:standard": "standard", 10 | "build": "babel src/ --out-dir lib/ --source-maps inline", 11 | "watch": "npm run build -- --watch", 12 | "clean": "rm -rf lib/*" 13 | }, 14 | "keywords": [ 15 | "socket.io", 16 | "reqres", 17 | "request", 18 | "response" 19 | ], 20 | "author": "Sho Hashimoto ", 21 | "license": "MIT", 22 | "devDependencies": { 23 | "babel-cli": "^6.26.0", 24 | "babel-polyfill": "^6.26.0", 25 | "babel-preset-es2015": "^6.6.0", 26 | "babel-preset-stage-0": "^6.5.0", 27 | "babel-register": "^6.26.0", 28 | "chai": "^4.1.2", 29 | "mocha": "^3.5.0", 30 | "npm-run-all": "^4.1.1", 31 | "socket.io": "^2.0.3", 32 | "socket.io-client": "^2.0.3", 33 | "standard": "^10.0.3" 34 | }, 35 | "dependencies": { 36 | "combine-middlewares": "^0.1.0", 37 | "deserialize-error": "^0.0.3", 38 | "serialize-error": "^2.0.0" 39 | }, 40 | "directories": { 41 | "test": "test" 42 | }, 43 | "repository": { 44 | "type": "git", 45 | "url": "git+https://github.com/shokai/socket.io-request.git" 46 | }, 47 | "bugs": { 48 | "url": "https://github.com/shokai/socket.io-request/issues" 49 | }, 50 | "homepage": "https://github.com/shokai/socket.io-request#readme" 51 | } 52 | -------------------------------------------------------------------------------- /test/disconnect.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 3 | import {assert} from 'chai' 4 | import {Server, port} from './helper' 5 | 6 | import Client from 'socket.io-client' 7 | 8 | import ioreq, {SocketIOError} from '../src/' 9 | 10 | const server = Server() 11 | 12 | describe('handling disconnect error', function () { 13 | describe('server disconnect', function () { 14 | it('should throw error', function (done) { 15 | server.on('connection', (socket) => { 16 | ioreq(socket).response('disconnect', (req, res) => { 17 | socket.disconnect() 18 | }) 19 | }) 20 | 21 | const client = Client(`http://localhost:${port}`) 22 | client.once('connect', async () => { 23 | var err, res 24 | try { 25 | res = await ioreq(client).request('disconnect') 26 | } catch (_err) { 27 | err = _err 28 | } 29 | assert.isUndefined(res) 30 | assert.equal(err.name, SocketIOError.name) 31 | assert.equal(err.message, 'disconnect') 32 | done() 33 | }) 34 | }) 35 | }) 36 | 37 | describe('client disconnect', function () { 38 | it('should throw error', function (done) { 39 | const client = Client(`http://localhost:${port}`) 40 | client.once('connect', () => { 41 | ioreq(client).response('disconnect', (req, res) => { 42 | client.disconnect() 43 | }) 44 | }) 45 | 46 | server.on('connection', async (socket) => { 47 | var err, res 48 | try { 49 | res = await ioreq(socket).request('disconnect') 50 | } catch (_err) { 51 | err = _err 52 | } 53 | assert.isUndefined(res) 54 | assert.equal(err.name, SocketIOError.name) 55 | assert.equal(err.message, 'disconnect') 56 | done() 57 | }) 58 | }) 59 | }) 60 | }) 61 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import {convertErrorToObject, convertObjectToError, TimeoutError, SocketIOError} from './error' 2 | import combineMiddlewares from 'combine-middlewares' 3 | 4 | export default class SocketIORequest { 5 | constructor (io, options = {}) { 6 | this.io = io 7 | this.options = Object.assign({ 8 | event: 'socket.io-request', 9 | timeout: 90000 10 | }, options) 11 | } 12 | 13 | request (method, data) { 14 | if (typeof method !== 'string') throw new Error('argument "method" is missing') 15 | 16 | return new Promise((resolve, reject) => { 17 | this.io.emit(this.options.event, {method, data}, (res) => { 18 | clearTimeout(timeout) 19 | this.io.removeListener('disconnect', onDisconnect) 20 | if (res.error) return reject(convertObjectToError(res.error)) 21 | resolve(res.data) 22 | }) 23 | 24 | const onDisconnect = () => { 25 | clearTimeout(timeout) 26 | reject(new SocketIOError('disconnect')) 27 | } 28 | 29 | const timeout = setTimeout(() => { 30 | this.io.removeListener('disconnect', onDisconnect) 31 | reject(new TimeoutError(`exceeded ${this.options.timeout} (msec)`)) 32 | }, this.options.timeout) 33 | 34 | this.io.once('disconnect', onDisconnect) 35 | }) 36 | } 37 | 38 | response (method, ...middlewares) { 39 | if (typeof method !== 'string') throw new Error('argument "method" is missing') 40 | if (middlewares.find(m => typeof m !== 'function')) { 41 | throw new Error('"middlewares" must be a function') 42 | } 43 | const combined = combineMiddlewares(...middlewares.concat()) 44 | this.io.on(this.options.event, (req, ack) => { 45 | if (req.method !== method) return 46 | const res = data => ack({data}) 47 | res.error = err => ack({error: convertErrorToObject(err)}) 48 | combined(req.data, res) 49 | }) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /test/error.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 3 | import {convertErrorToObject, convertObjectToError} from '../src/error' 4 | import {assert} from 'chai' 5 | 6 | describe('convertErrotToOjbect', function () { 7 | it('convert Error to Object', function () { 8 | const err = new Error('this is error') 9 | const obj = convertErrorToObject(err) 10 | assert.equal(obj.name, 'Error') 11 | assert.equal(obj.message, 'this is error') 12 | assert.isUndefined(obj.stack) 13 | assert.isObject(obj) 14 | }) 15 | 16 | it('convert Error in Array', function () { 17 | const errs = [ new Error('this is error') ] 18 | const objs = convertErrorToObject(errs) 19 | assert.equal(objs[0].name, 'Error') 20 | assert.equal(objs[0].message, 'this is error') 21 | assert.isUndefined(objs[0].stack) 22 | assert.isObject(objs[0]) 23 | }) 24 | 25 | it('convert Error in nested Object', function () { 26 | const errs = { foo: new Error('this is error'), bar: new Error('barbar') } 27 | const objs = convertErrorToObject(errs) 28 | assert.equal(objs.foo.name, 'Error') 29 | assert.equal(objs.foo.message, 'this is error') 30 | assert.isUndefined(objs.foo.stack) 31 | assert.isObject(objs.foo) 32 | assert.equal(objs.bar.name, 'Error') 33 | assert.equal(objs.bar.message, 'barbar') 34 | assert.isUndefined(objs.bar.stack) 35 | assert.isObject(objs.bar) 36 | }) 37 | }) 38 | 39 | describe('convertObjectToErrot', function () { 40 | it('convert Object to Error', function () { 41 | const obj = convertErrorToObject(new Error('this is error')) 42 | const err = convertObjectToError(obj) 43 | assert.equal(err.name, 'Error') 44 | assert.equal(err.message, 'this is error') 45 | assert.instanceOf(err, Error) 46 | }) 47 | 48 | it('convert Error in Array', function () { 49 | const objs = convertErrorToObject([ new Error('this is error') ]) 50 | const errs = convertObjectToError(objs) 51 | assert.equal(errs[0].name, 'Error') 52 | assert.equal(errs[0].message, 'this is error') 53 | assert.instanceOf(errs[0], Error) 54 | }) 55 | 56 | it('convert Error in nested Object', function () { 57 | const objs = convertErrorToObject({ foo: new Error('this is error'), bar: new Error('barbar') }) 58 | const errs = convertObjectToError(objs) 59 | assert.equal(errs.foo.name, 'Error') 60 | assert.equal(errs.foo.message, 'this is error') 61 | assert.instanceOf(errs.foo, Error) 62 | assert.equal(errs.bar.name, 'Error') 63 | assert.equal(errs.bar.message, 'barbar') 64 | assert.instanceOf(errs.bar, Error) 65 | }) 66 | }) 67 | -------------------------------------------------------------------------------- /test/request_response_error.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 3 | import {assert} from 'chai' 4 | import {Server, port} from './helper' 5 | 6 | import Client from 'socket.io-client' 7 | 8 | import ioreq from '../src/' 9 | 10 | const server = Server() 11 | 12 | describe('req.error(err)', function () { 13 | it('return error', function () { 14 | server.on('connection', (socket) => { 15 | ioreq(socket).response('req-error', (req, res) => { 16 | return res.error(new Error('something wrong')) 17 | }) 18 | }) 19 | 20 | const client = Client(`http://localhost:${port}`) 21 | client.once('connect', async () => { 22 | let res, err 23 | try { 24 | res = await ioreq(client).request('req-error', {msg: 'hello'}) 25 | } catch (_err) { 26 | err = _err 27 | } 28 | assert.isUndefined(res) 29 | assert.instanceOf(err, Error) 30 | assert.equal(err.name, 'Error') 31 | assert.equal(err.message, 'something wrong') 32 | }) 33 | }) 34 | 35 | it('return nested error', function () { 36 | server.on('connection', (socket) => { 37 | ioreq(socket).response('req-error-nested', (req, res) => { 38 | return res.error({foo: new Error('something wrong'), bar: 'bar'}) 39 | }) 40 | }) 41 | 42 | const client = Client(`http://localhost:${port}`) 43 | client.once('connect', async () => { 44 | let res, errs 45 | try { 46 | res = await ioreq(client).request('req-error-nested', {msg: 'hello'}) 47 | } catch (_errs) { 48 | errs = _errs 49 | } 50 | assert.isUndefined(res) 51 | assert.instanceOf(errs.foo, Error) 52 | assert.equal(errs.foo.name, 'Error') 53 | assert.equal(errs.foo.message, 'something wrong') 54 | }) 55 | }) 56 | 57 | it('return error array', function () { 58 | server.on('connection', (socket) => { 59 | ioreq(socket).response('req-error-array', (req, res) => { 60 | return res.error(['foo', 'bar', new Error('something wrong')]) 61 | }) 62 | }) 63 | 64 | const client = Client(`http://localhost:${port}`) 65 | client.once('connect', async () => { 66 | let res, errs 67 | try { 68 | res = await ioreq(client).request('req-error-array', {msg: 'hello'}) 69 | } catch (_errs) { 70 | errs = _errs 71 | } 72 | assert.isUndefined(res) 73 | assert.equal(errs[0], 'foo') 74 | assert.equal(errs[1], 'bar') 75 | assert.instanceOf(errs[2], Error) 76 | assert.equal(errs[2].name, 'Error') 77 | assert.equal(errs[2].message, 'something wrong') 78 | assert.isString(errs[2].stack) 79 | }) 80 | }) 81 | }) 82 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # socket.io-request 2 | 3 | bidirectional request-response for socket.io 4 | 5 | - https://github.com/shokai/socket.io-request 6 | - https://npmjs.com/package/socket.io-request 7 | 8 | [![Circle CI](https://circleci.com/gh/shokai/socket.io-request.svg?style=svg)](https://circleci.com/gh/shokai/socket.io-request) 9 | 10 | ## Feature 11 | Of cource, Socket.IO's `emit` and `on` have request-response. This library adds some features. 12 | 13 | - Promise interface 14 | - Exception handling 15 | - `timeout` 16 | - `disconnect` 17 | 18 | 19 | ## Install 20 | 21 | % npm install socket.io-request -save 22 | 23 | ## Methods 24 | 25 | - `request("method", data)` return `Promise` 26 | - `response("method", handler)` 27 | 28 | 29 | ## Usage 30 | 31 | ### request from Client to Server 32 | 33 | client 34 | 35 | ```javascript 36 | var ioreq = require("socket.io-request"); 37 | var io = require("socket.io-client")("http://localhost:3000"); 38 | 39 | io.on("connect", function(){ 40 | ioreq(io).request("toUpper", "hello world") // method, data 41 | .then(function(res){ 42 | console.log(res); // get "HELLO WORLD" 43 | }) 44 | .catch(function(err){ 45 | console.error(err.stack || err); 46 | }); 47 | }); 48 | ``` 49 | 50 | server 51 | 52 | ```javascript 53 | var ioreq = require("socket.io-request"); 54 | var io = require("socket.io")(3000); 55 | 56 | io.on("connection", function(socket){ // new client 57 | ioreq(socket).response("toUpper", function(req, res){ // method, handler 58 | res(req.toUpperCase()); // return to client 59 | }); 60 | }); 61 | ``` 62 | 63 | 64 | ### request from Server to Client 65 | 66 | server 67 | 68 | ```javascript 69 | var ioreq = require("socket.io-request"); 70 | var io = require("socket.io")(3000); 71 | 72 | io.on("connection", function(socket){ // new client 73 | ioreq(io).request("windowSize") 74 | .then(function(res){ 75 | console.log(res); // get {height: 528, width: 924} 76 | }); 77 | }); 78 | ``` 79 | 80 | client (web browser) 81 | 82 | ```javascript 83 | var ioreq = require("socket.io-request"); 84 | var io = require("socket.io-client")("http://localhost:3000"); 85 | 86 | io.on("connect", function(){ 87 | ioreq(io).response("windowSize", function(req, res){ 88 | res({ 89 | height: window.innerHeight, 90 | width: window.innerWidth 91 | }); // return to server 92 | }); 93 | }); 94 | ``` 95 | 96 | ### Error handling 97 | 98 | `res.error` returns error object to requester. 99 | 100 | ```javascript 101 | ioreq(io).response("foo", function(req, res){ 102 | if(typeof req !== "string") return res.error(new Error("request is not String")); 103 | res("foo!" + req); 104 | }); 105 | ``` 106 | 107 | ```javascript 108 | ioreq(io).request("foo", 123) 109 | .then(function(res){ 110 | console.log(res); 111 | }) 112 | .catch(function(err){ 113 | console.error(err); // => "[Error: request is not String]" 114 | }); 115 | ``` 116 | 117 | 118 | ### Options 119 | 120 | ```javascript 121 | var options = { 122 | event: "socket.io-request", // event name on socket.io 123 | timeout: 90000 // request timeout (msec) 124 | }; 125 | 126 | ioreq(io, options).request("foo"); 127 | ``` 128 | 129 | ## Async-Await 130 | 131 | Using [async-await syntax](https://github.com/tc39/ecmascript-asyncawait), you can write like below. 132 | 133 | ```javascript 134 | async () => { 135 | const res = await ioreq(io).request("hello"); 136 | }; 137 | ``` 138 | 139 | 140 | ## Samples 141 | 142 | in `./sample` directory. 143 | 144 | 145 | ## Develop 146 | 147 | % npm i 148 | % npm run build 149 | % npm test 150 | --------------------------------------------------------------------------------