0

I have object whith method (function) on server (node.js). I want get this object with methods in browser.

Is it possible?

I made simple example on GitHub

There are server.js and index.html files. Run --> node server.

++++++++ UPD (after comments)

My object on server:

function ClassOrder(name, cost) {
  this.name = name;
  this.cost = cost;
  this.parts = [];
  this.summ = function() {
    var summ = 0;
    this.parts.forEach(function(part) {
      summ += part.summ();
    });
    return summ + this.cost;
  };
}

var myobject = new ClassOrder('my object', 10);
myobject.parts[0] = new ClassOrder('my first part', 20);
myobject.parts[1] = new ClassOrder('my second part', 30);
myobject.parts[1].parts[0] = new ClassOrder('my first in second part', 40);

console.log(myobject); // view myobject in console
console.log(myobject.summ());  // return 100 (10+20+30+40)

send to client (on request)

res.end(JSON.stringify(myobject));

and get it on client's javascript code (in browser)

function getobject() {

  var xhr = new XMLHttpRequest();
  xhr.open('get', '/getobject', true);

  xhr.onreadystatechange = function() {
    if (xhr.readyState != 4) return; 

    var myobject = JSON.parse(this.responseText);

    console.log(myobject); // all data ok
    console.log(myobject.summ()); // no methods!! 

  };
  xhr.send(null);
}

It is a simple example and in real i use prototype (or inherit in util(node.js)). I use this methods on server and save it in DB. All work is ok. But if i wont use it on client i need copy-paste all methods, WHY?

Also i dont know how add my example method to my object in client without disassemble it.

pofigizm
  • 131
  • 1
  • 7
  • Technically you could serialize the function code and evaluate it on the client side, but why? I'd argue it makes the code harder to maintain and follow. – Felix Kling Jun 15 '14 at 00:29
  • Please distill down the relevant code and place that into your question. There are two reasons for this: 1) You will get a lot more people willing to understand and respond to your question is the code is distilled down to just the relevant code and placed into your question and 2) Part of the usefullness of StackOverflow is as a longer lasting resource for Q&A and external references to the code that a question is about tend to disappear or change over time ruining the utility of the question and link to code. – jfriend00 Jun 15 '14 at 02:23
  • @Felix Kling Becouse i dont want have double code. – pofigizm Jun 15 '14 at 06:53
  • @jfriend00 I add a important part of my code to my question. You are right. – pofigizm Jun 15 '14 at 06:55
  • Then organize your code so that you can include the class definition on the client and the server side. – Felix Kling Jun 15 '14 at 07:16
  • I dont understand what do you mean (may be because my English is not well). I already include class definition on the server side, but i cant include it on client side. – pofigizm Jun 15 '14 at 07:44
  • I mean you should put your class definition in its own file, and write it in such a way that you can include it server side an client side. Maybe you have to use some build tools or other dependency management library for that, but that would be a much cleaner way, than sending JS down via Ajax. – Felix Kling Jun 15 '14 at 18:33
  • I already do it. Thank you. – pofigizm Jun 15 '14 at 18:43
  • Yeah, I didn't realize you answered your own question. However, you shouldn't end your answer with a question. – Felix Kling Jun 15 '14 at 18:47

2 Answers2

0

The question was: how can I get on server and client identical objects with methods without doublecoding.

There are two way do it.

The first way is convert my methods (function) to text and save it with object. Then we can use Function constructor to run it.

function ClassOrder(name, cost) {
  this.name = name;
  this.cost = cost;
  this.parts = [];

  this.summfunc = '\
    var summ=0; \
    obj.parts.forEach(function(part) { \
      summ += part.summ(); \
    }); \
    return summ + obj.cost;';
}

ClassOrder.prototype.summ = function() {
  return (new Function('obj', this.summfunc))(this);
};

and can use it in browser

var myobject = JSON.parse(this.responseText);

myobject.constructor.prototype.summ = function() {
  return (new Function('obj', this.summfunc))(this);
};

Link to commit on new branch on GItHub

This way is bad because i need all my methods convert to text. And how say @Felix Kling it makes the code harder to maintain and follow.

The second way is use one file with classes and methods on server and on client. And ufter receive data "convert" it to my class.

my class in file order.js (part of file):

function Order(object) {
  object.parts = object.parts || [];
  var partsArr = [];
  object.parts.forEach(function (value, key) {
    partsArr[key] = new Order(value);
  });

  this.name = object.name || 'Default';
  this.cost = object.cost || 0;
  this.parts = partsArr;
}

Order.prototype.summ = function() {
  var summ = 0;
  this.parts.forEach(function(part) {
    summ += part.summ();
  });
  return summ + this.cost;
};

require order.js and change arguments of call new Object:

var Order = require('./order')

var myobject = new Order({name:'my object', cost: 10});
myobject.parts[0] = new Order({name:'my first part', cost: 20});
myobject.parts[1] = new Order({name:'my second part', cost: 30});
myobject.parts[1].parts[0] = new Order({name:'my first in second part', cost: 40});

and finaly use this file on client:

<script src='order.js'></script>
...
var xhrobj = JSON.parse(this.responseText);
var myobject = new Order(xhrobj);

Link to commit on other branch on GItHub

I think this way is better then first.

Russia Must Remove Putin
  • 374,368
  • 89
  • 403
  • 331
pofigizm
  • 131
  • 1
  • 7
  • Your second way won't work since your are not exporting anything from `order.js`. You'd have to add something like `if (module && module.exports) { module.exports = Order; }`. But it's the right approach. *Edit:* I see that you doing something similar in your Github example. – Felix Kling Jun 15 '14 at 18:35
  • I don't place here all text of my files, because it will be hard to understand main thing. I wrote that is a part of file. All files for this examlpe i placed on github as new commit to one-class branch. I am testing my examle and it work. Thank you for comment. – pofigizm Jun 15 '14 at 19:20
  • It's ok to answer your own question, but don't make it look like another question on top of the first one. – Russia Must Remove Putin Jun 16 '14 at 01:31
-1

I think the answer is right there: Calling a JavaScript function returned from an Ajax response

But it seems that isn't necessary to put the answers in a script tag, try this:

eval(this.responseText)
Community
  • 1
  • 1
user3739239
  • 146
  • 3