Mam klasy tak:Jak mogę kontrolować przepływ programu za pomocą zdarzeń i obietnic?
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);
}
}
Jak bym włączyć metodę send
do obietnicy, która zwraca wartość z gniazdka za data
wydarzenia? Serwer wysyła dane tylko wtedy, gdy do nich są wysyłane dane, inne niż wiadomość o połączeniu, którą można łatwo zignorować.
Próbowałem coś takiego:
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);
});
}
Oczywiście to nie zadziała, ponieważ resolve
/reject
zastąpi siebie podczas łączenia i/lub dzwoniąc send
wielokrotnie równolegle.
Istnieje również problem dwukrotnego równoległego wywoływania send
i rozstrzyganie, która odpowiedź zostanie zwrócona jako pierwsza.
Mam obecnie implementację za pomocą kolejki i odradzam, ale czuje się niechlujnie, ponieważ kolejka jest stale sprawdzana.
Chciałbym być w stanie wykonać następujące czynności:
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));
Wystarczy dodać, że nie mają żadnej kontroli nad danymi, które są odbierane, co oznacza, że nie mogą być modyfikowane na zewnątrz strumień.
Edytuj: Wydaje się więc, że jest to całkiem niemożliwe, ponieważ TCP nie ma przepływu żądania-odpowiedzi. W jaki sposób można to zrealizować nadal przy użyciu obietnic, ale przy użyciu pojedynczego wykonania (jeden wniosek na raz) obietnicy łańcucha lub kolejki.
To znaczy, jak dwukierunkowy czat? Wyślij jedną wiadomość i poczekaj, aż otrzymasz jedną wiadomość, tak? – thefourtheye
@ thefourtheye Prawie, z wyjątkiem tego, że potrzebuję wywołać 'send' równolegle, a obietnica powinna zwrócić poprawną odpowiedź w zależności od tego, co zostało wysłane. Chociaż wszystkie otrzymane dane pochodzą z jednego strumienia, więc nie można ich dokładnie zidentyfikować. –
Zgaduję, że ... czy mógłbyś ustawić jakiś obiekt obserwatora w 'socket' za pomocą metody' .add() ', a następnie wywołać' this.socket.observer.add ({ \t \t \t odrzucić: odrzucać, \t \t \t resolve: rozwiązać \t \t}; '' z send() ' –