Home>

Previous words

Error handling is crucial for web application development,It is not possible to predict possible errors in advance,Can't take recovery strategy in advance,May lead to poor user experience.As any javascript error may render the webpage unusable,So as a developer,You have to know when something might go wrong,Why is it wrong,And what could go wrong.This article will detail the error handling mechanism in javascript

error object

The error object is an object containing error information,Is a javascript native object.An error occurred when the code was parsed or run,The javascript engine will automatically generate and throw an instance of the error object,Then the entire program is interrupted where the error occurred

console.log (t);//uncaught referenceerror:t is not defined

Ecma-262 specifies that the error object includes two attributes:message and name. The message property holds the error message,While the name attribute holds the wrong type

//Generally, use try-catch statements to catch errors
try {
 t;
} catch (ex) {
 console.log (ex.message);//t is not defined
 console.log (ex.name);//referenceerror
}

The browser has also extended the properties of the error object,Added other relevant information.Among them, the most implemented by browser vendors is the stack attribute, which represents stack trace information (not supported by safari)

try {
 t;
} catch (ex) {
 console.log (ex.stack);//@file:///d:/wamp/www/form.html:12:2
}

Of course, you can use the error () constructor to create an error object.If the message parameter is specified, the error object will use it as its message property;if not specified,It will use a predefined default string as the value of the attribute

new error ();
new error (message);
//Generally, throw statements are used to throw errors
throw new error ("test");//uncaught error:test
throw new error ();//uncaught error

function usererror (message) {
 this.message=message;
 this.name="usererror";
}
usererror.prototype=new error ();
usererror.prototype.constructor=usererror;
throw new usererror ("errormessage");//uncaught usererror:errormessage

When calling the error () constructor as a function without using the new operator,It behaves the same as when called with the new operator

error ();
error (message);
throw error ("test");//uncaught error:test
throw error ();//uncaught error

The error object has a tostring () method, which returns "error:" + the message property of the error object

var test=new error ("testerror");
console.log (test.tostring ());//"error:testerror"

error type

Multiple There are many types of errors that can occur during code execution.Each error has a corresponding error type,And when an error occurs,An error object of the corresponding type will be thrown.ecma-262 defines the following 7 error types:

error
evalerror
rangeerror
referenceerror
syntaxerror
typeerror
urierror

Where error is the base type,All other error types are inherited from this type.Therefore, all error types share the same set of attributes.Errors of type error are rare,If any, it is also thrown by the browser;The main purpose of this base type is for developers to throw custom errors

[Evalerror]

When the eval function is not executed correctly,Evalerror will be thrown. This error type is no longer present in es5,Just to ensure compatibility with previous code,Just keep it

[Rangeerror]

Rangeerror type errors are triggered when a value exceeds the corresponding range,Mainly include exceeding the range of array length and exceeding the range of numeric values

new array (-1);//uncaught rangeerror:invalid array length
new array (number.max_value);//uncaught rangeerror:invalid array length
</p>
<p>
(1234) .toexponential (21);//uncaught rangeerror:toexponential () argument must be between 0 and 20
(1234) .toexponential (-1);////uncaught rangeerror:toexponential () argument must be between 0 and 20

[Referenceerror]

When referring to a non-existent variable or lvalue type error,Will trigger a referenceerror

a;//uncaught referenceerror:a is not defined

1 ++;//uncaught referenceerror:invalid left-hand side expression in postfix operation

[Syntaxerror]

When grammatical rules are not met,Throws syntaxerror

//Variable name
var 1a;//uncaught syntaxerror:unexpected number
//missing parentheses
console.log "hello");//uncaught syntaxerror:unexpected string

[Typeerror]

Time When an unexpected type is stored in a variable,Or when accessing a method that does not exist,Will cause typeerror.Although there are many reasons for the error,But in the end it ’s because when performing certain types of operations,The type of the variable does not meet the requirements

var o=new 10;//uncaught typeerror:10 is not a constructor
alert ("name" in true);//uncaught typeerror:cannot use "in" operator to search for "name" in true
function.prototype.tostring.call ("name");/uncaught typeerror:function.prototype.tostring is not generic

[Urierror]

Urierror is an error thrown when the parameters of a uri-related function are incorrect,It mainly involves six functions:encodeuri (), decodeuri (), encodeuricomponent (), decodeuricomponent (), escape (), and unescape ().

decodeuri ("%2");//urierror:uri malformed

error event

Any error that is not handled by try-catch will trigger the error event of the window object

The error event can receive three parameters:the error message, the url where the error is located, and the line number. in most cases,Only error messages are useful,Because the url just gives the location of the document,The line of code refers to either the embedded javascript code or an external file

To specify the onerror event handler,Can use dom0 level technology or standard format for dom2 level events

//dom0 level
window.onerror=function (message, url, line) {
 alert (message);
}
//dom2 level
window.addeventlistener ("error", function (message, url, line) {
 alert (message);
});

Does the browser display standard error messages,Depends on the return value of onerror.If the return value is false, an error message is displayed in the console;Do not display if the return value is true

//The console displays an error message
window.onerror=function (message, url, line) {
 alert (message);
 return false;
}
a;
//The console does not display an error message
window.onerror=function (message, url, line) {
 alert (message);
 return true;
}
a;

event This event handler is the last line of defense to prevent browsers from reporting errors.Ideally,It should not be used whenever possible.As long as you can use the try-catch statement appropriately, no errors will be passed to the browser,It will not trigger the error event

Image also supports error event. As long as the url in the src attribute of the image cannot return an image format that can be recognized,Will trigger an error event. The error event at this time follows the dom format and will return an event object targeting the image

caveat A warning box is displayed when image loading fails.When the error event occurs, the image download process has ended,It ca n’t be downloaded again.

var image=new image ();
image.src="smilex.gif";
image.onerror=function (e) {
 console.log (e);
}

throw statement and throw error

The throw statement is used to throw an error.When an error is thrown,You must assign a value to the throw statement,What type is this value,No requirement

note [Note] the process of throwing an error is blocking,Subsequent code will not be executed

throw 12345;
throw "hello world";
throw true;
throw {name:"javascript"};

You can manually throw an error object using the throw statement

throw new error ("something bad happened");
throw new syntaxerror ("i don \" t like your syntax. ");
throw new typeerror ("what type of variable do you take me for?");
throw new rangeerror ("sorry, you just don \" t have the range. ");
throw new evalerror ("that doesn \" t evaluate. ");
throw new urierror ("uri, is that you?");
throw new referenceerror ("you didn \" t cite your references properly ");

Using the prototype chain, you can also create custom error types by inheriting error (the prototype chain is introduced in Chapter 6). At this point, you need to specify the name and message attributes for the newly created error type

The browser treats custom error types inherited from error,It's like treating other error types.If i want to catch the error you throw and treat it differently from browser errors,Useful for creating custom errors

function customerror (message) {
 this.name="customerror";
 this.message=message;
}
customerror.prototype=new error ();
throw new customerror ("my message");

Code When a throw statement is encountered, the code will immediately stop execution.Only when a try-catch statement captures the thrown value,The code will continue to execute

A more detailed explanation is:when an exception is thrown,The javascript interpreter immediately stops the currently executing logic,And jump to the nearest exception handler.Exception handlers are written in the catch clause of a try-catch statement.If the code block that throws the exception does not have an associated catch clause, the interpreter checks for higher-level closed code blocks,See if it has an associated exception handler.And so on,Until you find an exception handler.If the function that throws the exception does not handle its try-catch statement, the exception will propagate up to the code that called the function.In this case,Exceptions propagate up the lexical structure and call stack of JavaScript methods.If no exception handler is found,JavaScript will treat exceptions as program errors,And report to the user

Try catch statements and catch errors

Ecma-262 3rd edition introduced try-catch statements as a standard way to handle exceptions in javascript,Used to catch and handle errors

For example, the try clause defines the code block where the exception needs to be handled.The catch clause follows the try clause,When an exception occurs somewhere in the try block,Call the code logic in the catch.The catch clause is followed by a finally block, which places cleanup code,Regardless of whether an exception is raised in the try block,The logic inside the finally block is always executed.Although both catch and finally are optional,But the try clause needs at least one of them to form a complete statement

Try/catch/finally statement blocks need to be enclosed in curly braces,The curly braces are required here,Braces cannot be omitted even if there is only one sentence in the clause

try {

//generally speaking,The code here will work from start to finish without any problems

//But sometimes an exception is thrown,Either directly thrown by the throw statement,Or indirectly by calling a method

} catch (e) {

//If and only if the try statement block throws an exception,Will execute the code here

//Here you can get a reference to the error object or other values ​​thrown through the local variable e

//The code block here can handle this exception for some reason,You can also ignore this exception,You can also rethrow the exception through a throw statement

} finally {

//Regardless of whether the try statement throws an exception,The logic in finally is always executed,Ways to terminate a try block are:

//1, terminated normally,After the last statement of the statement block has been executed

//2 、 terminate by break, continue or return statement

//3, throw an exception,Exception caught by catch clause

//4, throw an exception,The exception was not caught,Continue to spread

}

In general, put all the code that may throw errors in the try block,And put the code for error handling in the catch block

If anything goes wrong in the try block,Will immediately exit the code execution process,Then the catch block is executed. At this point, the catch block will receive an object with an error message.The actual information contained in this object will vary from browser to browser,But common is a message attribute that holds error messages

[Note] Be sure to give a name to the error object,Blank will report a syntax error

try {
 q;
} catch (error) {
 alert (error.message);//q is not defined
}
//uncaught syntaxerror:unexpected token)
try {
 q;
} catch () {
 alert (error.message);
}

Catch accepts a parameter,Represents the value thrown by a try block

function throwit (exception) {
 try {
 throw exception;
 } catch (e) {
 console.log ("caught:" + e);
 }
}
throwit (3);//caught:3
throwit ("hello");//caught:hello
throwit (new error ("an error happened"));//caught:error:an error happened

Catch code block after catching errors,The program will not be interrupted,Will continue to execute according to the normal process

try {
 throw "something went wrong";
} catch (e) {
 console.log (111);
}
console.log (222);
//111
//222

To catch different types of errors,You can add a judgment statement in the catch code block

try {
 foo.bar ();
} catch (e) {
 if (e instanceof evalerror) {
 console.log (e.name + ":" + e.message);
 } else if (e instanceof rangeerror) {
 console.log (e.name + ":" + e.message);
 }
 //...
}

While the finally clause is optional in a try-catch statement,But once the finally clause is used,Its code is executed anyway.in other words,The code in the try block is all executed normally,The finally clause is executed;If the catch block is executed because of an error, the finally clause is still executed.As long as the code contains a finally clause, no matter what code is included in the try or catch statement block-even the return statement will not prevent the execution of the finally clause

//Because there is no catch statement block, the error is not caught.
After executing the finally block,The program is interrupted where the error is thrown
function cleansup () {
 try {
 throw new error ("An error has occurred ...");
 console.log ("This line will not execute");
 } finally {
 console.log ("Complete the cleanup");
 }
}
cleansup ();
//Finish the cleanup
//error:something went wrong ...

function testfinnally () {
 try {
 return 2;
 } catch (error) {
 return 1;
 } finally {
 return 0;
 }
}
testfinnally ();//0

[Note] The count value of the return statement is before the finally code block is run.Get it done

var count=0;
function countup () {
 try {
 return count;
 } finally {
 count ++;
 }
}
countup ();//0
console.log (count);//1
function f () {
 try {
 console.log (0);
 throw "bug";
 } catch (e) {
 console.log (1);
 return true;//this sentence would have been deferred until the end of the finally block
 console.log (2);//will not run
 } finally {
 console.log (3);
 return false;//this sentence will overwrite the previous return
 console.log (4);//will not run
 }
 console.log (5);//will not run
}
var result=f ();
//0
//1
//3
console.log (result);//false

[Tips] block-level scope

A common use of try-catch statements is to create block scopes,The declared variables are only valid inside the catch

Es6 introduced the let keyword to create a block-level scope for the variables it declares.However, in the current case of es3 and es5,Try-catch statements are often used to achieve similar effects

You can see from the following code,e exists only within the catch clause,Throws an error when trying to reference it from elsewhere

try {
 throw new error ();//throw an error
} catch (e) {
 console.log (e);//error (...)
}
console.log (e);//uncaught referenceerror:e is not defined

Common mistakes

core The core of error handling is to first know what errors will occur in the code.Since javascript is loosely typed,And it does n’t validate the parameters of the function,So errors only occur during code.Generally speaking,Three types of errors need attention:type conversion errors, data type errors, communication errors

[Type conversion error]

Type conversion errors occur when using an operator,Or when using other language structures that may automatically convert data types of values

Where a type conversion error is likely to occur is a flow control statement.Statements like if, before determining what to do next,Any value is automatically converted to a Boolean value.Especially if statements, if used incorrectly,Most error prone

Unused named variables are automatically assigned undefined values. The undefined value can be converted to a boolean value of false, so the if statement in the following function is actually only applicable when the third parameter is provided.The problem is,Not only undefined is converted to false, nor is it only a string value that can be converted to true. For example, if the third parameter is a value of 0, the test of the if statement will fail,The test for value 1 will pass

function concat (str1, str2, str3) {
 var result=str1 + str2;
 if (str3) {//Never do this
 result +=str3;
 }
 return result;
}

use Use non-boolean values ​​in flow control statements,Is a very common source of errors.To avoid such errors,It is necessary to actually pass a Boolean value in the condition comparison.In fact, this can be achieved by performing some form of comparison

function concat (str1, str2, str3) {
 var result=str1 + str2;
 if (typeof str3 == "string") {//more appropriate
 result +=str3;
 }
 return result;
}

[Data type error]

Javascript is loosely typed,Before using variables and function parameters,They are not compared to ensure that their data types are correct.To ensure that no data type errors occur,Only write appropriate data type detection code.In the case where an unexpected value is passed to a drawing function,Most prone to data type errors

//unsafe function,Any non-array value will cause an error
function reversesort (values) {
 if (values) {
 values.sort ();
 values.reverse ();
 }
}

Another common mistake is comparing parameters to null values.Comparing with null only ensures that the corresponding values ​​are not null and undefined. To ensure that the value passed in is valid,Detecting null values ​​alone is not enough

//unsafe function,Any non-array value will cause an error
function reversesort (values) {
 if (values!=null) {
 values.sort ();
 values.reverse ();
 }
}

If an object (not an array) containing a sort () method is passed,But error may occur when calling reverse () function

//unsafe function,Any non-array value will cause an error
function reversesort (values) {
 if (typeof values.sort == "function") {
 values.sort ();
 values.reverse ();
 }
}

Without knowing exactly what type should be passed in,It is best to use instanceof to detect its data type

//safe, non-array values ​​are ignored
function reversesort (values) {
 if (values ​​instanceof array) {
 values.sort ();
 values.reverse ();
 }
}

[Communication error]

With the rise of ajax programming,A web application loads information or functions dynamically during its life cycle,It has become commonplace.However, any communication between javascript and the server,May produce errors

The most common problem is before sending data to the server,Data is not encoded using encodeuricomponent ()

//error

//Call encodeuricomponent () for all strings after "redir =" can solve this problem

  • Previous Yii2 caching basic usage example
  • Next jQuery + css achieves a very beautiful horizontal navigation menu effect