1
votes

I have the following Express app:

router.js

var express = require('express');
var router = express.Router();
var exch = require("../exchanges/exch")();

router.get('/', function(req, res, next) {

    exch .getTicker((tick) => {
        res.send('get ticker exch: ' + JSON.stringify(tick));
    });

});

module.exports = router;

exch.js

var Kraken = require('kraken-api');
var moment = require('moment');
var _ = require('lodash');

/**
...code
**/

var Exchange = function(config) {
  _.bindAll(this);

  if(_.isObject(config)) {
    this.key = config.key;
    this.secret = config.secret;
    this.currency = config.currency.toUpperCase()
    this.asset = config.asset.toUpperCase();
  }

  this.pair = addPrefix(this.asset) + addPrefix(this.currency);
  this.name = 'kraken';
  this.since = null;

  this.kraken = new Kraken(this.key, this.secret);
}

Exchange.prototype.getTicker = function(callback) {
  var set = function(err, data) {
    if(!err && _.isEmpty(data))
      err = 'no data';

    else if(!err && !_.isEmpty(data.error))
      err = data.error;

    if (err)
      return console.log('unable to get ticker' + JSON.stringify(err));

    var result = data.result[this.pair];
    var ticker = {
      ask: result.a[0],
      bid: result.b[0]
    };
    callback(err, ticker);
  };

  this.kraken.api('Ticker', {pair: this.pair}, _.bind(set, this));
};

}

module.exports = Exchange;

As you can see I am including the object via require("...")(). However, I still get the following error:

Cannot read property 'getTicker' of undefined

TypeError: Cannot read property 'getTicker' of undefined at /home/ubuntu/workspace/routes/ticker.js:20:9 at Layer.handle [as handle_request] (/home/ubuntu/workspace/node_modules/express/lib/router/layer.js:95:5) at next (/home/ubuntu/workspace/node_modules/express/lib/router/route.js:137:13) at Route.dispatch (/home/ubuntu/workspace/node_modules/express/lib/router/route.js:112:3) at Layer.handle [as handle_request] (/home/ubuntu/workspace/node_modules/express/lib/router/layer.js:95:5) at /home/ubuntu/workspace/node_modules/express/lib/router/index.js:281:22 at Function.process_params (/home/ubuntu/workspace/node_modules/express/lib/router/index.js:335:12) at next (/home/ubuntu/workspace/node_modules/express/lib/router/index.js:275:10) at Function.handle (/home/ubuntu/workspace/node_modules/express/lib/router/index.js:174:3) at router (/home/ubuntu/workspace/node_modules/express/lib/router/index.js:47:12)

Why is this error occurring and how can I fix it?

3

3 Answers

1
votes

You're not creating an instance, thus you can't access a method on the prototype. You're actually just calling the constructor function Exchange exported by exch.js. Since the constructor function, when called directly, returns nothing (implicitly undefined), you get the error:

var exch = require("../exchanges/exch")(); //exch is undefined because Exchange as a function returns nothing

This does not setup the prototype because you haven't constructed an object, just called the function. Instead, use new to construct a new Exchange object:

var Exchange = require("../exchanges/exch");
var exch = new Exchange();

This will create a new Exchange object in which you can call getTicker from the prototype. Note: Make sure to pass config to the constructor!


Without new you could do a check in Exchange to see if you accidentally called it without new, and to return a new instance:

var Exchange = function(config) {
  if(!(this instanceof Exchange)) {
    return new Exchange(config);
  }
  //...
}

What this does is return a new instance of Exchange even if you called the function directly. Now you could use:

var exch = require("../exchanges/exch")();

But I would always prefer the former method of using new always for constructors.

0
votes

require("../exchanges/exch")() call the function rather than create a new instance, use new to instantiate in order to use the prototype. The reason you got undefined is that the Exchange returns nothing. You suppose it to be a constructor, but you call it as function

Use the code instead:

var exchModule = require("../exchanges/exch")
var exch=new exchModule()
0
votes

change last line of your code in exch.js

exports.exchange = Exchange;

now modify in router.js

var exch = require("../exchanges/exch").exchange;

var exchObject= new exch();

now you can use exchObject object to call methods