1.Introduction

ezyfox-es6-client is a client sdk of ezyfox-server written in javascript language and use ECMAScript 6 standardization, you can use it for any web application like ReactJS application, VueJS application and Angular application

2.How to install?

ezyfox-es6-client available on npm, you simple run:

npm i ezyfox-es6-client

ezyfox-es6-client source code available on Github, so you can clone and import to any project, you also modify the source code to fit you purpose

3.Create an ReactJS example

Let’s say you want to create a HelloWorld web application to say hello everyone available on EzyFox Server Firstly, we need download ezyfox-server lastest version and run it, if you don’t have Java 8, you need download and install it, this tutorial will help you, you also need setup JAVA_HOME path variable. If you don’t know how to run ezyfox-server, please read this tutorial Secondly, we need create a ReactJS application with name: hello-world, please read this tutorial if you don’t know how to create ReactJS application Thirdly, we need move to hello-world project’s folder an install ezyfox-es6-client by command: npm i ezyfox-es6-client After setup project, open it on Visual Studio Code and we have:

https://tvd12.com/wp-content/uploads/es6-reactjs-1.png

3.1 Add folders and Files to project

We need add:

  • socket folder: to place any files related to socket
  • SocketProxy.js: contains setup client, connect to server and handle request response
  • SocketRequest.js: contains request functions
  • views: to place any files related to views
  • LoginView.jsx: contains LoginView
  • HelloWorldView.jsx: contain HelloWorldView After create folders and files we have:

https://tvd12.com/wp-content/uploads/es6-reactjs-2.png

3.2 Import Mvc.js

Because ezyfox-es6-client only help us communicate with websocket, so we need a library to support to store data, show the data to view and controller user’s action. Mvc.js is a lightweight library support to us, let’s install it:

npm i mvc-es6

3.3 Implement SocketProxy.js

3.3.1 Create socket client

let config = new Ezy.ClientConfig;
config.zoneName = "example";
let clients = Ezy.Clients.getInstance();
let client = clients.newDefaultClient(config);

3.3.2 Setup socket client

let setup = client.setup;
setup.addEventHandler(Ezy.EventType.CONNECTION_FAILURE, connectionFailureHandler);
setup.addEventHandler(Ezy.EventType.DISCONNECTION, disconnectionHandler);
setup.addDataHandler(Ezy.Command.HANDSHAKE, handshakeHandler);
setup.addDataHandler(Ezy.Command.LOGIN, userLoginHandler);
setup.addDataHandler(Ezy.Command.APP_ACCESS, accessAppHandler);

3.3.3 Setup hello-world app

let setupApp = setup.setupApp("hello-world");
let helloWorldController = mvc.getController("helloWorld");
setupApp.addDataHandler("broadcastMessage", function(app, data) {
helloWorldController.updateViews("helloWorld", data['message']);
});

3.3.4 Connect to server

let url = "ws://localhost:2208/ws";
let client = this.getClient();
client.connect(url);

3.3.5 Create event and data handler classes

let mvc = Mvc.getInstance();
let models = mvc.models;
let handshakeHandler = new Ezy.HandshakeHandler();
handshakeHandler.getLoginRequest = function () {
    let connection = models.connection;
    let username = connection.username;
    let password = connection.password;
    return ["example", username, password, []];
};

let loginSuccessHandler = new Ezy.LoginSuccessHandler();
loginSuccessHandler.handleLoginSuccess = function () {
    let accessAppRequest = ["hello-world", []];
    this.client.sendRequest(Ezy.Command.APP_ACCESS, accessAppRequest);
};

let accessAppHandler = new Ezy.AppAccessHandler();
accessAppHandler.postHandle = function (app, data) {
    let routerController = mvc.getController("router");
    routerController.updateViews('change', '/');
};

let connectionFailureHandler = new Ezy.ConnectionFailureHandler();
connectionFailureHandler.control = function (event) {
    let connectionController = mvc.getController("connection");
    connectionController.updateViews("connectFailure", event.reason);
};

let disconnectionHandler = new Ezy.DisconnectionHandler();
disconnectionHandler.preHandle = function (event) {
    let connectionController = mvc.getController("connection");
    connectionController.updateViews("disconnect");
};

After all, we have the SocketProxy.cs with full content:

import Ezy from 'ezyfox-es6-client';
import Mvc from 'mvc-es6';

class SocketProxyClass {

    setup() {
        let mvc = Mvc.getInstance();
        let models = mvc.models;
        let handshakeHandler = new Ezy.HandshakeHandler();
        handshakeHandler.getLoginRequest = function() {
            let connection = models.connection;
            let username = connection.username;
            let password = connection.password;
            return ["example", username, password, []];
        };

        let loginSuccessHandler = new Ezy.LoginSuccessHandler();
        loginSuccessHandler.handleLoginSuccess = function() {
            let accessAppRequest = ["hello-world", []];
            this.client.sendRequest(Ezy.Command.APP_ACCESS, accessAppRequest);
        };

        let accessAppHandler = new Ezy.AppAccessHandler();
        accessAppHandler.postHandle = function(app, data) {
            let routerController = mvc.getController("router");
            routerController.updateViews('change', '/');
        };

        let connectionFailureHandler = new Ezy.ConnectionFailureHandler();
        connectionFailureHandler.control = function(event) {
            let connectionController = mvc.getController("connection");
            connectionController.updateViews("connectFailure", event.reason);
        };

        let disconnectionHandler = new Ezy.DisconnectionHandler();
        disconnectionHandler.preHandle = function(event) {
            let connectionController = mvc.getController("connection");
            connectionController.updateViews("disconnect");
        };

        let config = new Ezy.ClientConfig();
        config.zoneName = "example";
        let clients = Ezy.Clients.getInstance();
        let client = clients.newDefaultClient(config);
        let setup = client.setup;
        setup.addEventHandler(Ezy.EventType.CONNECTION_FAILURE, connectionFailureHandler);
        setup.addEventHandler(Ezy.EventType.DISCONNECTION, disconnectionHandler);
        setup.addDataHandler(Ezy.Command.HANDSHAKE, handshakeHandler);
        setup.addDataHandler(Ezy.Command.LOGIN, loginSuccessHandler);
        setup.addDataHandler(Ezy.Command.APP_ACCESS, accessAppHandler);
        
        let setupApp = setup.setupApp("hello-world");
        let helloWorldController = mvc.getController("helloWorld");
        setupApp.addDataHandler("broadcastMessage", function(app, data) {
            helloWorldController.updateViews("message", data['message']);
        });
        
        return client;
    }

    connect() {
        let url = "ws://localhost:2208/ws";
        let client = this.getClient();
        client.connect(url);
    }

    isConnected() {
        let client = this.getClient();
        let connected = client && client.isConnected();
        return connected;
    }

    getClient() {
        let clients = Ezy.Clients.getInstance();
        let client = clients.getDefaultClient();
        return client;
    }
}

var socketProxyInstance = socketProxyInstance || new SocketProxyClass();

class SocketProxySingleton {

    getInstance() {
        return socketProxyInstance;
    }

}

var SocketProxy = SocketProxy || new SocketProxySingleton();

export default SocketProxy;

3.4 Implement SocketRequest.js

import Ezy from 'ezyfox-es6-client';

class SocketRequestClass {

    sendBroadcastMessage(message) {
        this.getApp().sendRequest('broadcastMessage', {message : message});
    }

    getClient() {
        let clients = Ezy.Clients.getInstance();
        let client = clients.getDefaultClient();
        return client;
    }

    getApp() {
        let zone = this.getClient().zone;
        let appManager = zone.appManager;
        let app = appManager.getApp();
        return app;
    }

}

let SocketRequest = SocketRequest || new SocketRequestClass();

3.5 Implement LoginView.jsx

3.5.1 Add CSS

Replace App.css by follow code:

body {font-family: Arial, Helvetica, sans-serif;}

h2 {
  text-align:center;
}

input[type=text], input[type=password] {
  width: 250px;
  padding: 12px 20px;
  margin: 8px 0;
  display: inline-block;
  border: 1px solid #ccc;
  box-sizing: border-box;
}

button {
  background-color: #4CAF50;
  color: white;
  padding: 14px 20px;
  margin: 8px 0;
  border: none;
  cursor: pointer;
  width: 200%;
}

button:hover {
  opacity: 0.8;
}

.container {
  padding: 16px;
  display: flex;
  flex-direction: column;
  align-items: center;
}

label {
  padding-right:5px;
}

.error {
  color: red;
}

.big-message {
  color: crimson;
  margin-top: 50px;
}

3.5.2 Code LoginView.jsx

import React, { Component } from 'react';
import Mvc from 'mvc-es6'
import SocketProxy from './../socket/SocketProxy'

class LoginView extends Component {
    constructor() {
        super(...arguments);
        this.state = {
            username: 'monkey',
            password: '123456'
        };

        this.onUsernameChanged = this.onUsernameChanged.bind(this);
        this.onPasswordChanged = this.onPasswordChanged.bind(this);
        this.onLogin = this.onLogin.bind(this);

        this.mvc = Mvc.getInstance();
        this.connectionController = this.mvc.getController("connection");
    }

    onUsernameChanged(e) {
        this.setState({
            username: e.target.value,
        });
    };

    onPasswordChanged(e) {
        this.setState({
            password: e.target.value,
        });
    }

    onLogin(e) {
        e.preventDefault();
        let models = this.mvc.models;
        let connection = models.connection || {};
        connection.username = this.state.username;
        connection.password = this.state.password;
        models.connection = connection;
        let socketProxy = SocketProxy.getInstance();
        socketProxy.connect();
    }

    componentDidMount() {
        this.connectionController.addDefaultView("connectFailure", msg => {
            this.setState({"connectFailureMsg" : msg});
        });
    }

    componentWillUnmount() {
        this.connectionController.removeViews();
    }

    render() {
        let {connectFailureMsg} = this.state;
        return (
            <div>
                <h2>Login Form</h2>

                <div className="container">
                    <div>
                        <label htmlFor="uname"><b>Username</b></label>
                        <input type="text" 
                            placeholder="Enter Username" 
                            onChange={this.onUsernameChanged}
                            name="username" defaultValue="monkey" required />
                    </div>
                    <div>
                        <label htmlFor="psw"><b>Password</b></label>
                        <input type="password" 
                            placeholder="Enter Password" 
                            onChange={this.onPasswordChanged}
                            name="password" defaultValue="123456" required />
                    </div>
                    <div>
                        <button onClick={this.onLogin}>Login</button>
                    </div>
                    <div>
                        <p className="error">{connectFailureMsg ? "Login error: " + connectFailureMsg : ""}</p>
                    </div>
                </div>
            </div>
        );
    }
}
export default LoginView;

3.6 Implement HelloWorldView.js

import React, { Component } from 'react';
import Mvc from 'mvc-es6'
import SocketRequest from './../socket/SocketRequest'

class HelloWorldView extends Component {
    constructor() {
        super(...arguments);
        this.state = {
            message: 'Hello World'
        };
        this.mvc = Mvc.getInstance();
        this.helloWorldController = this.mvc.getController("helloWorld");
    }

    componentDidMount() {
        this.helloWorldController.addDefaultView('message', message => {
            this.setState({message : message});
        })
        SocketRequest.sendBroadcastMessage("Hello everyone, I'm a young monkey");
    }
  
    render() {
        let {message} = this.state;
        return (
            <div>
                <h2 className="big-message">{message}</h2>
            </div>
        );
    }
}
export default HelloWorldView;

3.7 Update App.js

import Ezy from 'ezyfox-es6-client';
import Mvc from 'mvc-es6';
import React, { Component } from 'react';
import './App.css';
import LoginView from './views/LoginView'
import HelloWorldView from './views/HelloWorldView'
import SocketProxy from './socket/SocketProxy'

class App extends Component {
  constructor() {
    super(...arguments);
    this.state = {currentViewURI: ""};

    // setup ezyfox
    Ezy.Logger.debug = () => true;
    this.clients = Ezy.Clients.getInstance();
    
    this.mvc = Mvc.getInstance();
    this.mvc.newController("connection");
    this.mvc.newController("login");
    this.mvc.newController("helloWorld");
    this.mvc.newController("router");

    // setup socket
    this.socketProxy = SocketProxy.getInstance();
    this.socketProxy.setup();
  }

  componentDidMount() {
    let routerController = this.mvc.getController("router");
    routerController.addDefaultView("change", viewURI => {
      this.setState({currentViewURI : viewURI});
    });
  }

  render() {
    let {currentViewURI} = this.state;
    let view;
    switch(currentViewURI) {
      case "/":
        view = <HelloWorldView />;
        break;
      case "/login":
        view = <LoginView />;
        break;
      default:
        view = <LoginView />;
        currentViewURI = "/login";
        break;
    };
    window.history.pushState('', '', currentViewURI);
    return (
     
        <div>
            {view}
        </div>

    );
  }

}

export default App;

Now, run command:

npm start

And we have:

https://tvd12.com/wp-content/uploads/es6-reactjs-3.png

https://tvd12.com/wp-content/uploads/es6-reactjs-4.png

4.Conclusion

ezyfox-es6-client help you connect to ezyfox-server and you don’t need care about socket client and byte bit to send to server, everything is simple