background

With the continuous development of Web development, the separation of front and back ends has already changed from a trend to the daily configuration of project development. After separation, the division of labor is more clear, and the development efficiency is improved. But at the same time, the interface has become the only channel for communication between the front and back ends, and the dependence of the front-end page on the accuracy of interface data is unprecedented. Usually the back end negotiates the API format and it works fine, but things don’t always work that well…

The problem echoes a common scenario in front-end careers:

Product (out of breath) : Quick! User feedback page white page, your front end quick look! Front end (after a debug) : The interface has a field not transmitted, you go to RD to ask the front end heart: it is not my pot, why do you frighten me every time: Js can try to read a property that does not exist in an object, but if even the object does not exist, JS will report an error and block subsequent code execution. /* API reserved format :{code:0, data:{house:{name: ‘XX apartment ‘, tags: {code:0, data:{}} / const response = await http.post(url); LocalName = response.data.house.name; localName = response.data.house.name; / API Reserved format :{code:0, data:{house:{name: ‘XX apartment ‘, tag: }}} {code:0, data:{house:{name: ‘XX apartment ‘, tag: {}}}} */ const response = await http.post(url); / / return of the format is not an array, object without pop method, error and stop execution lastTag = response. Data. House. Tags. The pop (); Data out of range: for example, the string length exceeds the interface definition, resulting in the placement of page elements. Locating the root cause Both sides of the interface should verify data before performing logic based on the principle of mutual distrust. In order to prevent attackers from forging requests, the backend often has to do a lot of data verification. But the front end requests its own server, so security is guaranteed, so in most cases the front end does not validate the data returned by the back end, which is usually fine, of course, until the product comes panting to you.

/* API reserved format :{code:0, data:{house:{name: ‘XX apartment ‘, tag: }}} */ const response = await http.post(url); if (response.code! =0){console.log(‘code error ‘)} if (! Response.data){console.log(‘data missing ‘)} if (response.data&&! {the console. The log response. Data. House) (‘ lack of data. The house ‘)} / /… Typescript: Ts is not strongly typed. It is extremely tedious and is not recommended. With Ts! Conclusion: Ts is static and only useful at compile time, not for data returned dynamically by this interface. The final solution is to use nodeJS to write the server interface since the data is so troublesome. Looking around, I found something called class-Validator, which is the default tool in the NestJS framework. Does this thing work on the front end?

Can!!!! This probably looks like to use the import {validate, ValidateNested IsNotEmpty, Equals, Length, IsArray} from “class – the validator”; let hasOwnProperty = Object.prototype.hasOwnProperty; let propIsEnumerable = Object.prototype.propertyIsEnumerable;

Class House {@length (10, 20,{message: ‘name cannot be less than 10 or more than 20’}) @isnotempty ({message:’name cannot be empty ‘}) name: string;

@isarray ({message:' array cannot be empty '}) tags: object;Copy the code

}

class Data { @ValidateNested() house: House;

constructor() {
    this.house = new House();
}
Copy the code

}

class ResponseData { @ValidateNested() data: Data;

@Equals(0)
code: number

constructor() {
    this.data = new Data();
}
Copy the code

}

Let data = {code: 0, data: {house: {name: “‘, tags: [‘ whole ‘]},},}

let post = new ResponseData();

deepAssign(post,data)

validate(post).then(errors => { if (errors.length > 0) { console.log(errors); } else {console.log(” Success!” ); }}); Conclusion The error message of the validation attribute value can be customized, like @isarray ({message:’ array cannot be empty ‘}) or the default message can be used, like this

The validate method returns an array of ValidationError objects [{“target”: {“data”: {“house”: {“name”: “DDDD “, “tags”: “Whole”}}, “code” : 2}, “value” : {“, “house” : {” name “:” DDDD “, “tags” : [” rental “]}}, “property” : “data”, “children” : [{” target “: {“,” house “: {” name” : “DDDD”, “tags” : [” rental “]}}, “value” : {” name “:” DDDD “, “tags” : “Whole”}, “property” : “, “house”, “children” : [{” target “: {” name” : “DDDD”, “tags” : [” rental “]}, “value” : “DDDD “, “property”: “name”, “children”: [], “constraints”: {“length”: “name cannot be less than 10 or more than 20”}}]}]}, {“target”: {” data “: {“,” house “: {” name” : “DDDD”, “tags” : [” rental “]}}, “code” : 2}, “value” : 2, “property” : “code”, “children” : [], “constraints”: {“equals”: “code must be equal to 0”}}] // Check the object property: string; // Failed attribute value: any; // Constraints? : {// Validation failed with error message constraint [type: string]: string; }; children? : ValidationError[]; // All nested validationErrors for this attribute} Conclusion: The level of nesting in the ValidationError array may be deep, so we can use a recursive algorithm to extract the required information. This is where the class-Validator is less than ideal.

Further improve user experience

  1. If errors are unavoidable… Make it look good for non-fatal errors, fill it with default data, and show page fatal errors, jumping to a friendly error page
  2. It’s a stupid thing to actively report errors and passively wait for feedback from users or products. At this time, countless times have passed and countless users have been affected. As a company “users first, we can’t allow this kind of situation, the first person to found the problem should be the developer, we need to have the ability to take the initiative to find and call the police The project access front-end monitoring system of apm front-end monitoring system is to monitor the front error message and the front end of an error in the form of mail sent to the developer, This allows developers to find errors first and resolve them in time. To report an error message, the validate method Validate (post). Then (errors => {if (errors.length > 0) {window.apm.report({errmsg:” data is empty “, errorData: Json.stringify (errors)})} else {console.log(” Success!” ); }});