I am trying to build a variable number of arguments routine for better error messages with the context.
I am looking for a JavaScript solution that can run in NodeJS.
Let me first explain my requirement with code:
In file licenseNotificationMessages.js
const licenseNotificationMessages = {
CapacityAlmostExpired:{
description: 'my description contains $1 followed by $2 followed by $3 in this case.,
},
CapacityExpired:{
description: 'my description contains $1 followed by $2 in this case.,
},
}
const constructMessage = (message, ...var_args_array) => {
// TODO. Replace the message's occurrences of $1, $2, $3 ... $N by var_args_array[0],
// var_args_array[1], .... var_args_array[N].
}
module.exports = {
licenseNotificationMessages,
constructMessage,
}
I want to use it something like:
In another file exporting licenseNotificationMessages
const { licenseNotificationMessages, constructMessage } = require('./licenseNotificationMessages');
description = licenseNotificationMessages.constructMessage(licenseNotificationMessages.CapacityAlmostExpired.description, ['val_for_$1', 'val_for_$2', 'val_for_$3']);
......
description = licenseNotificationMessages.constructMessage(licenseNotificationMessages.CapacityExpired.description, ['val_for_$1', 'val_for_$2']);
Not getting any clue how to achieve it in JavaScript in Node JS environment. (I am in node 16 ).
Any pointer will be helpful here.
CodePudding user response:
Error classes
In my opinion, defining a few error classes is often the best solution when having different errors with different messages:
export class CustomError extends Error {
constructor(...args) {
super(`Some message with ${args[0]} and ${args[1]} mentioned in it`);
};
}
export class CapacityAlmostExpiredError extends Error {
constructor(capacityUsed, capacityLimit) {
super(`Used capacity (${capacityUsed} MB) almost exceeds the limit of ${capacityLimit} MB`);
};
}
console.log
with placeholders
If you can afford to immediately log the message (without having access to the message string), then using console.log
with placeholders would be very elegant, - but you'll have to change the placeholder pattern:
console.log(messageWithPlaceholders, ...args);
In your case it's this:
const message = "my description contains %s followed by %s followed by %s in this case."; // notice lack of numbers
console.log(message, 'val_for_the_first_%s', 'val_for_the_second_%s', 'val_for_the_third_%s');
Iterating arguments
With all that said, if the constructMessage
approach is strictly necessary for whatever reason, you would have to iterate the arguments list, get an index of each argument, convert the index into a placeholder, find this placeholder in the string, and replace it with the argument's value:
function constructMessage(string, args) {
let message = string;
for (const [ index, arg ] of args.entries()) {
const placeholder = "$" (index 1); // 0 becomes '$1'
message = message.replace(placeholder, arg);
}
return message;
}