JSONRPC API:圆形对象=不良体系结构?

时间:2019-07-02 10:15:36

标签: node.js pg-promise node-https

  • 列表项

我需要创建一个JSON RPC API,该API必须管理Postgre数据库。 我的应用程序由服务器和带回购协议的数​​据库组成。

公开的方法来自每个存储库的“方法”属性。

我的问题是(我认为)我没有使用好的架构,因为每个回购中都有一个圆形对象: 在每个回购中,“ db”属性包括所有回购(包括他本人)。例如:DevicesRepository.db = -所有pg-promise函数 -所有其他存储库(RolesRepository,ShellsRepository ...) -DevicesRepository(设备存储库) 那是问题吗 ?我认为那意味着我的架构不好?

我在存储库中也有关于'this'的问题,如果不是相同的问题,我将打开另一个问题

我的API如何工作:

  1. ./ server / server.js从./db/index.js获取方法
  2. ./ db / index.js使用'Object.assign()'对一个对象中的所有repo.method进行“重新组合”
  3. 在每个存储库中,我都必须绑定“ this”(示例= DevicesRepository),否则方法(此处为“ add”)不知道this.db是什么。
  4. 因为我将上下文绑定到方法“ this.db”起作用,但是在“ tx”调用中,上下文是this.db,所以我不能再使用this.Collections

./ db / repos / devices.js

'use strict';

class DevicesRepository {
  constructor(db, pgp) {
    this.db = db;
    this.pgp = pgp;

    this.Collections = createColumnsets(pgp);

    this.methods = {
        'devices.insert': this.add.bind(this),
    }
  }

  async add(params) {
    console.log(this); //here this = DevicesRepository
    var device = params.data.device;

    return this.db.tx(function* (transaction) {
      console.log(this); // here this = transaction = DevicesRepository.db

      const system = yield transaction.systems.add(params);
      device.systemid = system.systemId;

      const query = this.pgp.helpers.insert(device, this.Collections.insert);  // this.pgp = undefined
      if(params.return) query += " RETURNING *";

      return transaction.one(query);
    })
    .then(data => {
      // hidden
    })
    .catch(ex => {
      // hidden
    });
  }
}

/* hidden for brevity */

module.exports = DevicesRepository;

./ db / repos / index.js

'use strict';

module.exports = {
    // other repo are required with the same way
  Devices: require('./devices'),
};

./ db / index.js

'use strict';

const repos = require('./repos'); // ./repos/index.js
const conf = require('./conf');

// pg-promise initialization options:
const initOptions = {
    //promiseLib: promise, // Use a custom promise library, instead of the default ES6 Promise:
    extend(obj, dc) {
      // other repo are added with the same way
        obj.devices = new repos.Devices(obj, pgp);
    }
};

const pgp = require('pg-promise')(initOptions);
const db = pgp(config);

const methods = Object.assign({},
    db.roles.methods,
    db.shells.methods,
    db.systems.methods,
    db.devices.methods,
);

module.exports = {
  methods,
}

./ server / server.js

const http = require('http');
const Database = require('../db'); //  ./db/index.js

const path = '/api/v1', port = 9000;
const methods = Database.methods;

const requestHandler = (req, res) => {
  //some lines are hidden for brevity
  const body = [];
  req.on('data', (chunk) => {
    body.push(chunk);
  }).on('end', () => {
    const bodyStr = Buffer.concat(body).toString();

    // parse body en JSON
    let request = JSON.parse(bodyStr);

    requestProcessor(request).then((response) => {
      sendResponse(res, response);
    });
  });
}

async function requestProcessor(request) {
  //some lines are hidden for brevity
  let response = { /* some properties */ };

  try {
    response.result = await Promise.resolve(methods[request.method](request.params)); // call the repo method
  } catch (err) {
    // hidden
  }

  return response;
}

const server = http.createServer(requestHandler);
server.listen(port, (err) => {
  if(err) {
    return Log('something bad happened', err);
  }
  Log(`server is listening on ${port}`);
};

0 个答案:

没有答案