greengold
greengold

Reputation: 1333

instances of module functions/classes in nodejs

I have a project that was started as ES5.1, later I changed it to support ES6 so I was using async-await, let...

now I need to have module/object that is instance-like.

I found this post explaining the process, but...

when I do:

'use strict';

let _ = require('lodash');
var mappings;

function SafeRequestHandler(reqMappings) {

    if (!(this instanceof SafeRequestHandler)) {
        return new SafeRequestHandler((reqMappings));
    }

    mappings = reqMappings;
}

function safeHandleReq(req, res) {
    try {
        let pair = _.find(mappings, {'url': req.url});
        return pair.handler(req, res);
    } catch (err) {
        console.log(err);
    }
}

SafeRequestHandler.prototype.safe = safeHandleReq;

module.exports = SafeRequestHandler;

but now, each time I do:

var handler = require('../util/safeRequestHandler');

let handlerMappings = [
    {
        url: def.party_create,
        handler: partyCreate
    },
    {
        url: def.party_modify,
        handler: partyModify
    },
    {
        url: def.party_get,
        handler: partyGet
    }
];

var handle = new handler(handlerMappings).safe;

I get this.mappings REPLACED in SafeRequestHandler eg. it's NOT an instance.

so I tried ES6 approach defining the handler:

'use strict';

let _ = require('lodash');

class SafeRequestHandler {

    constructor(reqMappings) {
        this.mappings = reqMappings;
    }

    safeHandleReq(req, res) {
        try {
            let pair = _.find(this.mappings, {'url': req.url});
            return pair.handler(req, res);
        } catch (err) {
            console.log(err);
        }
    }

}

and instantiate it like:

let handlerMappings = [
    {
        url: def.party_create,
        handler: partyCreate
    },
    {
        url: def.party_modify,
        handler: partyModify
    },
    {
        url: def.party_get,
        handler: partyGet
    }
];

let handle = new SafeRequestHandler(handlerMappings).safeHandleReq;

..but this way I can't even reach out mappings in safeHandleReq(...). this is undefined, mappings is undefined

I think I just don't fully understand basic principles, so can you please correct&explain what is wrong with this two approaches?

Thanks!

Upvotes: 0

Views: 63

Answers (2)

Hitmands
Hitmands

Reputation: 14189

You will lose the context if you store a method of a specific class instance into a variable.

// handle doesn't have a pointer to its context (aka, this)
let handle = new SafeRequestHandler(handlerMappings).safeHandleReq;
// so handle() will output cannot read property mappings of undefined

Change it to:

const instance = new SafeRequestHandler(handlerMappings);

const handle = (...args) => instance.safeHandleReq(...args);

Further info here: Losing "this" context in JavaScript when passing around members

Upvotes: 1

Jonas Wilms
Jonas Wilms

Reputation: 138317

Your first code creates a global variable, so theres just one value. You might use this there too:

 let _ = require('lodash');
function SafeRequestHandler(reqMappings) {
  if (!(this instanceof SafeRequestHandler)) {
    return new SafeRequestHandler((reqMappings));
  }
   this.mappings = reqMappings;
}

SafeRequestHandler.prototype.safeHandleReq =  function(req, res) {
    try {
        let pair = _.find(this.mappings, {'url': req.url});
        return pair.handler(req, res);
    } catch (err) {
        console.log(err);
    }
}
module.exports = SafeRequestHandler;

Upvotes: 0

Related Questions