synrc / n2o

⭕ N2O: Distributed WebSocket Application Server ISO 20922
https://ws.n2o.dev
Other
1.34k stars 168 forks source link

How can I get a return value from an N2O event ? #299

Closed hamdijmii1992 closed 7 years ago

hamdijmii1992 commented 7 years ago

I called an N2O event from my javascript client, then I want that the N2O event renders a json object to my client. Actually, I have an event as follows:

event({client,{refresh_event,Data}}) ->
        %connect to a database and get a document 
     [Doc];

I am able to call my event correctly, but in my onmessage callback I didn't get any thing useful, I always get an empty object although my Doc object is not empty.

My onmessage callback is as follows:

ws.onmessage = function onMessage(evt) { 
    if((evt.data != "PONG")){
     console.log(utf8_dec(evt.data));       
   }
  };  

I think that I missed something, can I have a hook to solve my issue please ?

5HT commented 7 years ago

If you use your own message loop then everything is up to you. In n2o we have following schema:

  1. implement you own handler (there is no handler for server messages, only for bin
    var $bin = {}; $bin.on = function onbin(r, cb) { if (is(r,2,'bin')) {
    if (typeof cb == 'function') cb(r); return { status: "ok" }; }
    else return { status: '' }; }

    Include your proto handler:

    $bert.protos = [$io,$bin,$file];

    use it on server side:

    event(#bin{data=Data}) ->
    wf:info(?MODULE,"Binary Delivered ~p~n",[Data]),
    #bin{data = "SERVER"};

Internally n2o client loop is implemented like this:

var $bert = {};
      $bert.protos = [$io,$bin,$file];
      $bert.on = function onbert(evt, cb) {
    if (Blob.prototype.isPrototypeOf(evt.data) &&
       (evt.data.length > 0 || evt.data.size > 0)) {
        var r = new FileReader();
        r.addEventListener("loadend", function() {
            try { erlang = dec(r.result);
                  if (debug) console.log(JSON.stringify(erlang));
                  if (typeof cb  == 'function') cb(erlang);
                  for (var i=0;i<$bert.protos.length;i++) {
                    p = $bert.protos[i];
                    if (p.on(erlang, p.do).status == "ok") return; }
            } catch (e) { console.log(e); } });
        r.readAsArrayBuffer(evt.data);
        return { status: "ok" }; } else return { status: "error", desc: "data" }; }

So probably you need just to steal from this following code:

if (Blob.prototype.isPrototypeOf(evt.data) && 
    (evt.data.length > 0 || evt.data.size > 0)) {
        var r = new FileReader();
        r.addEventListener("loadend", function() {
            try { erlang = dec(r.result);
                    ....              
hamdijmii1992 commented 7 years ago

Sorry I used the standard N2o message loop, I sent my message as follows:

 setTimeout(function () { ws.send(enc(tuple(atom('client'),
                  tuple(atom('refresh_event'),bin("hello")))));       
                  }, 1000);

How can I receive in the onmessage callback a valid json data from N2o page ?

5HT commented 7 years ago

BIN stands for binary. It is not intended to use JSON in Binary prototocol. Please read about protocols http://synrc.com/apps/n2o/doc/web/protocols.htm for JSON traffic you need just to put

{n2o, [{formatter,json},
       ...

but anyway you will receive:

 {"t":104,"v":[{"t":100,"v":"bin"},
                       {"t":107,"v":"SERVER v1"}]}

This is not JSON you are expected. To use real JSON you need to use synrc/rest or synrc/bert applications.

5HT commented 7 years ago

BIN stands for binary. It is not intended to use JSON in Binary prototocol. Please read about protocols http://synrc.com/apps/n2o/doc/web/protocols.htm for JSON traffic you need just to put

 {n2o, [{port,8000},
            {formatter,json},

but anyway you will receive:

{"t":104,"v":[{"t":100,"v":"bin"},
                    {"t":107,"v":"SERVER v1"}]}

This is not JSON you are expected. Isn't it? To use what you really want you need not n2o, but synrc/bert or synrc/rest apps.