I want to arrange async server-client communication with websockets and vanilla flux architecture. There is an excellent article about "Async Server-Side Communication with the Flux Architecture". I gonna implement it analogue with SockJS and ES6 promises:
TodoActionCreator.js
import { dispatchAsync } from '../AppDispatcher';
import ActionTypes from '../constants/ActionTypes';
import TodoService from '../services/TodoService'
export function addTodo(text) {
var that = this;
TodoService.addTodo({text: text}).then(function(todo) {
that.dispatch(ActionTypes.ADD_TODO, todo);
});
}
TodoService.js
import WebSocketWrapper from '../communication/WebSocketWrapper';
export function addTodo(todo) {
//maybe do something with todos before send them to the server
return WebSocketWrapper.send(todo);
}
WebSocketWrapper.js
/**
* Due fact that SockJS provide raw websocket API and do not implement pub/sub, we need to do wrapper, which will corellate request/response
*/
import SockJS from 'sockjs-client';
import selectn from 'selectn';
var responseDeffers = {},
requestId = 1;
var webSocketWrapper = {
join: function(url) {
this.ws = new SockJS(url);
this.ws.onopen = this.onOpen;
this.ws.onmessage = this.onMessage;
this.ws.onclose = this.onClose;
this.ws.onerror = this.onError;
},
onMessage: function(message) {
let requestId = selectn('message.data.request_id');
if (!requestId) return;
//resolve or reject the promise which is kept in ActionCreator
if (message.data.result === 'Ok') resolveRequest(requestId, message);
else rejectRequest(requestId, message.error);
},
/**
* Return Promise, which will be resolved/rejected on server response with the same requestId
*/
send: function(request) {
return new Promise(function(resolve, reject) {
//npm run build
// cache resolve/reject function to be able to invoke themn on server response
responseDeffers[requestId++] = {
resovle,
reject
};
//send message via websockets
if (this.ws.readyState == this.ws.OPEN) {
this.ws.send(JSON.stringify(request));
} else {
reject('Websocket connection is closed');
}
});
},
resolveRequest: function(requestId, message) {
let response = JSON.parse(message.data);
responseDeffers[request_id].resolve(response);
delete responseDeffers[request_id];
},
rejectRequest: function(requestId, message) {
responseDeffers[requestId].reject(message);
},
onOpen: function() {},
oClose: function() {},
onError: function(e) {}
}
webSocketWrapper.join('http://localhost:3000/sjs');
export default webSocketWrapper;