最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - es6 classes with express.js, how to pass instance of class so that each route can access? - Stack Overflow

programmeradmin1浏览0评论

I have a class class defined to keep track of some dynamic data that will be updated during runtime. I want the instance of this class to be accessible by all routes I have defined in my application:

export default class Manager {
  constructor() {
    let self = this;
    self.table = [];
  }
  addEntity(obj){
    let self = this;
    self.table.push(obj);
  }
}

Let's say I run my app and some event happens. I then invoke manager.addEntity(...some_event...);.

self.table will then have a new element. I want to be able to have a route access this information by requesting the route's url, maybe GET /api/table/. Unfortunately I currently have no way of accessing the instance of the class.

Should I assign the reference to the instance of the class to a global variable? This is an anti-pattern and I'd like to avoid doing this if possible.

My server is defined using normal remended code:

import http from 'http';
import { env, mongo, port, ip, apiRoot } from './config';
import api from './api';
import express from './services/express';
import mongoose from './services/mongoose';
import Manager from './lib/manager.js';

const app = express(apiRoot, api);

const server = http.createServer(app);

mongoose.connect(mongo.uri, { useMongoClient: true });
mongoose.Promise = Promise;

new Manager().initialize(server);

setImmediate(() => {
  server.listen(port, ip, () => {
    console.log(
      'Express server listening on http://%s:%d, in %s mode',
      ip,
      port,
      env,
    );
  });
});

export default app;

I have a class class defined to keep track of some dynamic data that will be updated during runtime. I want the instance of this class to be accessible by all routes I have defined in my application:

export default class Manager {
  constructor() {
    let self = this;
    self.table = [];
  }
  addEntity(obj){
    let self = this;
    self.table.push(obj);
  }
}

Let's say I run my app and some event happens. I then invoke manager.addEntity(...some_event...);.

self.table will then have a new element. I want to be able to have a route access this information by requesting the route's url, maybe GET /api/table/. Unfortunately I currently have no way of accessing the instance of the class.

Should I assign the reference to the instance of the class to a global variable? This is an anti-pattern and I'd like to avoid doing this if possible.

My server is defined using normal remended code:

import http from 'http';
import { env, mongo, port, ip, apiRoot } from './config';
import api from './api';
import express from './services/express';
import mongoose from './services/mongoose';
import Manager from './lib/manager.js';

const app = express(apiRoot, api);

const server = http.createServer(app);

mongoose.connect(mongo.uri, { useMongoClient: true });
mongoose.Promise = Promise;

new Manager().initialize(server);

setImmediate(() => {
  server.listen(port, ip, () => {
    console.log(
      'Express server listening on http://%s:%d, in %s mode',
      ip,
      port,
      env,
    );
  });
});

export default app;
Share Improve this question asked Jan 24, 2018 at 19:41 PGTPGT 2,0392 gold badges27 silver badges49 bronze badges 1
  • Sounds like you are indeed looking for a global variable. There's only one instance of your class for your whole application? – Bergi Commented Jan 24, 2018 at 21:09
Add a ment  | 

2 Answers 2

Reset to default 3

Edit: Refer to the ment by Bergi below as to why the answer I posted is a bad idea.

--

Export a instance of that class that all the routes import. Instead maybe something like this (single instance pattern):

class Manager {
    ...
}

export default new Manager();

Whether singleton class is justified or not is decided on per case basis.

It can be justified if the use of a class can provide certain benefits:

  • a class may be instantiated multiple times, while there should exist default instance

  • a class may be extended

  • a class can provide syntactic or functional benefits (for instance, drastic performance optimization for prototype chain in Node.js/V8)

If there's a chance that it has to be instantiated multiple times (nested applications, testing, etc.), it can be a class with default instance. This is naturally provided by JS modules, including ES modules:

export class Manager {
  constructor() {
    this.table = [];
  }
  addEntity(obj) {
    this.table.push(obj);
  }
}

export default new Manager();

Notice that Manager is exported in case there's a need to instantiate or extend it.

If this is not the case, then KISS principle can be applied, and plain object can be used instead:"

export default {
  table: [],
  addEntity(obj) {
    this.table.push(obj);
  }
};

KISS principle can be applied further; if pushing an object to the array is all that the class does, addEntity isn't very helpful. It can be omitted, so we end up with a single array.

In Express.js, application-wide variables are conventionally stored as application settings, so the variable (either the entire object or table array) could be stored and retrieved from application instance:

app.set('managed entities', []);
...
app.get('managed entities').push(...);

The requirement is to have access to application instance, so the code that uses managed entities setting should reside inside middleware function. On the other hand, this provides more flexibility. The setting can be overridden if needed.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论