Home > Back-end >  Positional Association of variable number of arguments in Node JS for better error message construct
Positional Association of variable number of arguments in Node JS for better error message construct

Time:11-06

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);

enter image description here

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;
}
  • Related