I have a function with one parameter customerID
. This can be the ID of a company or private person. Because the database structure is badly build I have to check if it is a Company or PrivatePerson in two separate calls.
My approach now is to define two variables customer
and customer_type
both set to null. I fetch for a company. If a company is found I assign the company to the customer variable and set customer_type to 'company'. If no company is found a fetch to the PrivatePersons collection is made and checked if a PrivatePerson is found. If so the fetched data gets assigned to the customer and customer_type is set to 'PrivatePerson'.
The code underneath is working to do all of this but it feels messy. The if/else with another if inside the else just doesn't feel right. I can be wrong but I think there is a better approach to this. Anyway up to give some advice on this?
const myFunction = async (customerID) => {
let customer = null;
let customer_type = null;
const company = await Companies.findByID({ customerID });
if(company) {
customer = company;
customer_type = 'Company'
} else {
const private_person = await PrivatePersons.findByID({ customerID });
if(private_person) {
customer = private_person;
customer_type = 'PrivatePerson'
}
}
if(!customer) {
return
}
...
}
CodePudding user response:
The tersest edit would look like this:
const getCustomer = async (customerID) => {
let customer = await Companies.findByID({ customerID });
return customer || await PrivatePersons.findByID({ customerID });
}
In the function above, or anyplace upstream, the customer type can be checked with:
async function someCaller() {
const customer = await getCustomer(someId);
const customer_type = customer.constructor.modelName; // will be either 'Companies' or 'PrivatePersons'
// ...
}
edit
Generalizing, if the objective is to both find an object, and also convey where it was found, we need a little extra representation. A few ideas:
- If customers are ES6 objects, you can get the same effect as above with:
const customer = getCustomer(someId);
const customer_type = customer.constructor.name
- More generally, for generic objects, you could annotate the found object:
const getCustomer = async (customerID) => {
// say we have arrays called companies and privatePersons
let customer = companies.find(c => c.id === customerId);
if (customer) customer.type = 'Companies';
else {
customer = privatePersons.find(p => p.id === customerId);
customer?.type = 'PrivatePersons';
}
return customer;
}
1a. If the membership in one array or the other is pretty stable -- which it seems like it might be for your app -- then you can annotate the objects in advance...
companies = companies.map(c => ({ ...c, type: 'Companies' }));
privatePersons = privatePersons.map(p => ({ ...p, type: 'PrivatePersons' }));
Doing so simplifies getCustomer
to:
const getCustomer = async (customerID) => {
return companies.find(c => c.id === customerId) ||
privatePersons.find(p => p.id === customerId);
}
- Another idea is to augment the found object. Have the getCustomer function return an object/type pair, like this:
const getCustomer = async (customerID) => {
let type;
let customer = companies.find(c => c.id === customerId);
if (customer) type = 'Companies';
else {
customer = privatePersons.find(p => p.id === customerId);
type = 'PrivatePersons';
}
return { customer, type }
}
The caller instead of receiving the plain customer, would change like this...
let { customer, customer_type } = getCustomer(customerID);