Manwal
Manwal

Reputation: 23836

Javascript es6 class handling error

I have created a JS class. Here is following code:

export default class Service {
    constructor(
        serviceId,
        serviceName,
        serviceDescription,
        serviceImageName,
        categoryId,
        servicePrice,
        currencyCode,
        acceptPayment,
        serviceDuration,
        multipleBookingPerSlot,
        mode,
        tzSupport,
        minOptionCount
    ) {
        try{
            this.id = serviceId;
            this.title = serviceName;
            this.subTitle = serviceDescription;
            this.imageUrl = serviceImageName;
            this.categoryId = categoryId;
            this.price = servicePrice;
            this.currencyCode = currencyCode;
            this.acceptPayment = acceptPayment;
            this.meetingDuration = serviceDuration;
            this.multipleBookingPerSlot = multipleBookingPerSlot;
            this.serviceName = serviceName;
            this.mode = mode;
            this.tzSupport = tzSupport;
            this.session = minOptionCount
        } catch(e){
            if(e instanceof ReferenceError){
                console.error("Service data missing.")
            }
        }

    }
}

My goal is whenever new object of Service creates like new Service('1') if any of key is missing code should throw error and stop execution. How can i achieve this?

Upvotes: 1

Views: 180

Answers (2)

T.J. Crowder
T.J. Crowder

Reputation: 1075587

You won't get a ReferenceError if the caller doesn't supply enough arguments, you'll just see undefined in the parameters.

You have 13 parameters (which is far, far too many). You could do the brute-force thing:

if (arguments.length < 13) {
    throw new Error("Missing arguments");
}

Instead, though, I suggest using the builder pattern or an options object instead of 13 discrete parameters. More than three parameters is fairly hard to manage.

For instance, with an options object:

export default class Service {
    constructor(
        options
    ) {
        ["id", "title", "subTitle", "imageUrl", "categoryId", "price", "currencyCode",
        "acceptPayment", "meetingDuration", "multipleBookingPerSlot", "serviceName",
        "mode", "tzSupport", "session"].forEach(name => {
            if (!options.hasOwnProperty(name)) {
                throw new Error(name + " is a required option");
            }
        });
        Object.assign(this, options);
    }
}

Usage:

let s = new Service({id: 1, title: "foo", /*...etc...*/});

That way, the caller isn't lost in a sea of parameters.


However, if it's important to validate the parameter values are present, isn't it important to validate their values, too? Nothing's to stop me from calling new Service with 13 completely-invalid arguments (undefined repeated 13 times, for instance).

So I would probably use an options object (because it's much easier for the caller) combined with parameter destructuring, and then individual validation, e.g.:

export default class Service {
    constructor({                 // <== Notice the {
        id,
        name,
        decription,
        imageUrl,
        categoryId,
        price,
        currencyCode,
        acceptPayment,
        meetingDuration,
        multipleBookingPerSlot,
        mode,
        tzSupport,
        minOptionCount
    }) {                          // <== And the }
        this.id = validate.positiveNumber(id);
        this.title = validate.nonBlank(name);
        this.subTitle = validate.nonBlank(description);
        this.imageUrl = validate.URL(imageUrl);
        this.categoryId = validate.positiveNumber(categoryId);
        this.price = validate.price(price);
        this.currencyCode = validate.currencyCode(currencyCode);
        this.acceptPayment = validate.boolean(acceptPayment);
        this.meetingDuration = validate.duration(meetingDuration);
        this.multipleBookingPerSlot = validate.boolean(multipleBookingPerSlot);
        this.serviceName = this.title; // Already validated
        this.mode = validate.mode(mode);
        this.tzSupport = validate.tzSupport(tzSupport);
        this.session = validate.whateverThisIs(minOptionCount);
    }
}

...where validate is a set of reusable validations. Usage is the same as above:

let s = new Service({id: 1, title: "foo", /*...etc...*/});

Upvotes: 2

Jonas Wilms
Jonas Wilms

Reputation: 138537

As i already commented assigning undefined to an objects property is completely valid. The solution might be to check for the values of the arguments Arraylike against undefined:

constructor(a,b,c){
   if(arguments.length!=3){//check length
     return;
   }
   for(var a=0;a<arguments.length;a++){
      if(arguments[a]===undefined){//check against undefined
          return;
       }
    }
  //your code
}

http://jsbin.com/vugepakama/edit?console

Upvotes: 0

Related Questions