preface
Our defense here only talks about how to defend against the data sent by the back end. For example, you and the back end agree that our data format is as follows:
{
data: { // Data requires an object
personInfo: { // personInfo requires an object
name: 'Joe'.// The personInfo attribute must have a name attribute and be a string
age: 12.// The personInfo attribute must have an age attribute and be a number
},
...XXX // Other attributes are omitted
},
success: 0.0 indicates success. 1 indicates failure
}
Copy the code
If we want to use back-end data, I believe most of our front-end colleagues will write such code
// Simulate back-end data
const mockData = {
data: { // Data requires an object
personInfo: { // personInfo requires an object
name: 'Joe'.// The personInfo attribute must have a name attribute and be a string
age: 12.// The personInfo attribute must have an age attribute and be a number
},
...XXX // Other attributes are omitted
},
success: 0.0 indicates success. 1 indicates failure
}
Copy the code
Business use
// Check if it is an object
const isObj = (obj) = > Object.prototype.toString.call(obj).toLowerCase() == "[object object]";
if(mockData && mockData.data && isObj(mockData.data) && mockData.data.personInfo && isObj(mockData.data.personInfo)){ Only here can we safely use mockData.data.personinfo data}Copy the code
Some of you can use es6, right? The. Operator simplifies the above, as follows:
if(mockData? .data? .personInfo && isObj(mockData.data) && isObj(mockData.data.personinfo)){here you can use mockData.data.personinfo data with confidence}Copy the code
It seems a lot simpler, but we are defending and making all kinds of if judgments, which is really annoying, because the validation should be done in the Service layer, which is the fetch library where we request the data, or the XHR library in Axios. We added validation in the business layer, which itself does not meet the single responsibility principle.
solution
So how to let the service layer to do this, we can each request data, in the service layer to do a check, if the data format does not meet the format we discussed with the backend, then directly throw the wrong, do not go behind the logic.
In other words, we need to make sure that the data returned by the back end is 100% satisfactory so that the front end does not make defensive if judgments. (This is the perfect way to throw the pot to the back! The point! The point! The point!)
Some people say you can use typescript to do this, but it doesn’t work. Typescript only works at compile time, and when you pack it, the validation disappears. How can you make it work after you pack it?
Class – the validator very sweet
The solution was to use a library called class-Validator, which is basically a dependency library for simplified validation that must be used in conjunction with typescript because of decorators.
Usage:
import {validate, ValidateNested,Equals, Length, IsNotEmpty, IsNumber} from "class-validator";
// Construct a user type, the information for personInfo
// This class can be used both as typescript type validation and as class-validator
class User {
@Length(10.20, {message: 'Name cannot be less than 10 and cannot be greater than 20'})
@IsNotEmpty({message:'Name cannot be null'})
name: string;
@IsNumber({message:'Age field must be of type number'})
age: number;
}
class Data {
@ValidateNested()
user: User;
constructor() {
this.user = newUser(); }}class ResponseData {
@ValidateNested()
data: Data;
@Equals(0)
success: number
constructor() {
this.data = newData(); }}let data = {
data: {
personInfo: {
name: 'Joe'.age: 12,}},success: 0.0 indicates success. 1 indicates failure
}
Copy the code
Finally, verify the data
let post = new ResponseData();
validate(post).then(errors= > {
if (errors.length > 0) {
console.log(errors);
} else {
console.log("Success!); }})Copy the code
The business layer is used as a certain data, and the defensive judgment of back-end data needs to be used at a separate level, which will make the code simpler and more consistent with the single principle.