How to use app.service('myService') inside a FeathersJS service extension?

微笑、不失礼 提交于 2019-12-23 05:34:34

问题


I am trying to extend find() method for a service named properties in my FeathersJS app.

What I need is appending in all records returned by find() an array with integers coming from another service named propertyadds. This means I need to change my response from

{
  "total": 2973,
  "limit": 10,
  "skip": 0,
  "data": [
    {
      "id": 1,
      ...
    },
    {
      "id": 2,
      ...
    }
    ...
  ]
}

to

{
  "total": 2973,
  "limit": 10,
  "skip": 0,
  data: [
    {
      "id": 1,
      ...
      "additionals": [10,20,30]
    },
    {
      "id": 2,
      ...
      "additionals": [12,25,33]
    }
    ...
  ]
}

where the values in additionals come from service propertyadds, which manages a table like

| property_id | additional_id |
|-------------|---------------|
|      1      |       10      |
|      1      |       20      |
|      1      |       30      |
|      2      |       12      |
|      2      |       25      |
|      2      |       33      |
|-------------|---------------|

My initial idea was extending properties service like this

const { Service } = require('feathers-sequelize');

exports.Properties = class Properties extends Service {
  async find(data,params) {
      let newResponse = await super.find(data,params);
      let newData = newResponse.data.map(async pr => {
          pr.additionals = await app.service('propertyadds').find({
              properti_id: pr.id
          })
          return pr;
      })
      return {
          total: newResponse.total,
          limit: newResponse.limit,
          skip: newResponse.skip,
          data: newData
      }
  }
};

The problem is I don't have app inside src/services/properties/properties.class.js and (being new to FeathersJS as I am) I don't know how to get it.

What do I need to have a valid app const accessing all services inside this module?


回答1:


I don't know for feather-sequelize but according to doc

For services registered before app.listen is invoked, the setup function of each registered service is called on invoking app.listen...

By inheritating from Service (I don't know if that the standard way to do), maybe Service implements setup and you may access this.app from within Properties::find()

If you don't have it then write it:

async find(data,params) {
...
}
async setup(app, path){
  await super.setup && super.setup(app, path)
  // for now no setup on Service
  // should Service adds a setup, it is unlikely that it wraps app to a 
  // whole new object and assigns it to this, so we can still
  // assign app to this with a relative confidence
  this.app = app
}



回答2:


The solution was, in fact, achieved when I visited src/services/properties.service.js and found out this line

app.use('/properties', new Properties(options, app));

So, service properties was, in fact, receiving an app object in its creation.

Learning this made me see the correct solution, written in src/services/properties/properties.class.js like this:

const { Service } = require('feathers-sequelize');

exports.Properties = class Properties extends Service {

    constructor(options, app) {
        super(options, app);
        this.app = app;
    }

    async find(data, params) {
        let oldRes = await super.find(data, params);
        let newResData = oldRes.data.map(async pr => {
            let includedRecords = await this.app.service('propertyadds').find({
                query: {
                    property_id: pr.id
                }
            })
            pr.additionals = includedRecords.map(e => e.additional_id).sort();
            return pr;
        })
        return await Promise.all(newResData)
            .then(completed => {
                return {
                    total: oldRes.total,
                    limit: oldRes.limit,
                    skip: oldRes.skip,
                    data: completed
                }
            })
    }
}

As it may be seen, it was a matter of creating a constructor method for the extended Properties class, in order to expose the app object in this.app. This may be done after calling super(options,app) to make this available.

After this it was just a matter of using this.app to create an instance of the other service and then making the correct async calls.



来源:https://stackoverflow.com/questions/59361549/how-to-use-app-servicemyservice-inside-a-feathersjs-service-extension

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!