I have a class like:
import net from 'net'; import {EventEmitter} from 'events'; import Promise from 'bluebird'; class MyClass extends EventEmitter { constructor(host = 'localhost', port = 10011) { super(EventEmitter); this.host = host; this.port = port; this.socket = null; this.connect(); } connect() { this.socket = net.connect(this.port, this.host); this.socket.on('connect', this.handle.bind(this)); } handle(data) { this.socket.on('data', data => { }); } send(data) { this.socket.write(data); } }
How would I turn the send method into a promise that returns a value from the socket data event? The server sends data only when data is sent to it, except for a connection message, which can be easily disconnected.
I tried something like:
handle(data) { this.socket.on('data', data => { return this.socket.resolve(data); }); this.socket.on('error', this.socket.reject.bind(this)); } send(data) { return new Promise((resolve, reject) => { this.socket.resolve = resolve; this.socket.reject = reject; this.socket.write(data); }); }
Obviously, this will not work, because resolve / reject will overwrite each other when chaining and / or calling send several times in parallel.
There is also the problem of calling send twice in parallel, and it resolves the response to any answer.
I currently have an implementation using a queue and brute force, but it seems messy as the queue is constantly being checked.
I would like to be able to do the following:
let c = new MyClass('localhost', 10011); c.send('foo').then(response => { return c.send('bar', response.param); //`response` should be the data returned from `this.socket.on('data')`. }).then(response => { console.log(response); }).catch(error => console.log(error));
Just to add, I do not control the received data, that is, it cannot be changed outside the stream.
Edit : this seems to be rather complicated since TCP does not have a request-response stream. How can this be implemented using promises, but using a one-time (one request at a time) promise chain or queue.