问题
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