Contents
Preface
There are probably two reasons for the white screen. One is the loading of resources, and the other is JS execution errors.
This article summarizes the errors reported in JS, which can easily cause ” white screen ” scenarios, and some methods that can solve these problems.
common mistakes
SyntaxError
SyntaxError
(SyntaxError) objects represent errors in attempts to parse ungrammatical code. When the Javascript engine parses the code and encounters a token or token sequence that does not comply with the grammatical specification, it will be thrown
SyntaxError
.
SyntaxError
Common mistakes listed here
Reserved word error
SyntaxError: "x" is a reserved identifier
(Firefox)SyntaxError: Unexpected reserved word
(Chrome)
If you execute the code below on the console, the above error will appear.
const enum = 1
enum
They are reserved words in strict mode and non-strict mode .
The following tags are reserved words only in strict mode :
implements
interface
let
package
private
protected
public
static
For example:
const implements = 1 // ✅ "use strict" ; const implements = 1 ; // caught SyntaxError: Unexpected strict mode reserved word
Naming error
A JavaScript identifier must start with a letter, an underscore (_) or a dollar sign ($). They cannot start with a number. Only subsequent characters can be digits (0-9).
var 1life = 'foo' ; // SyntaxError: identifier starts immediately after numeric literal var foo = 1life; // SyntaxError: identifier starts immediately after numeric literal
wrong punctuation
There are illegal or unexpected symbols in the code where they should not appear.
" This looks like a string"; // SyntaxError: illegal character 42 – 13 ; // SyntaxError: illegal character
Chinese quotation marks and horizontal bars are used in the code, causing parsing errors. This reflects the importance of the editor.
JSON parsing
JSON . parse ( '[1, 2, 3, 4, ]' ); JSON . parse ( '{"foo" : 1, }' ); // SyntaxError JSON.parse: unexpected character // at line 1 column 14 of the JSON data
json
There are many types of parsing failures, so I won’t go into details here. json
When we parse, we must add try...catch
statements to avoid errors.
semicolon problem
Usually, this error is just the result of another error, such as incorrectly escaping strings or using var.
const foo = 'Tom's bar '; // SyntaxError: missing ; before statement
Declare through other schemes:
var foo = "Tom's bar" ; var foo = 'Tom\'s bar' ; var foo = `Tom's bar` ; // This solution is recommended
Use var
error
var array = []; var array[ 0 ] = "there" ; // SyntaxError missing ; before
There are many similar errors to the current ones, such as:
SyntaxError: missing ) after argument list
SyntaxError: missing ) after condition
SyntaxError: missing } after function body
SyntaxError: missing } after property list
These are grammatical errors that can be parsed during the use of the editor/IDE. However, in some older frameworks,
the editor may not recognize its syntax. This is the scenario where this error often occurs.
summary
SyntaxError
It is a runtime code error. It is usually an error that novice developers make easily. It dev
can be found during the period. Otherwise, it cannot pass the compilation. It is a problem that is relatively easy to find.
TypeError
TypeError
(TypeError) An error that occurs when an object is usually (but not exclusively) used to represent a value of an unexpected type.
The following situations will be thrown TypeError
:
- The operands passed to an operator or the arguments passed to a function are incompatible with the expected type;
- Attempt to modify a value that cannot be changed;
- An attempt was made to use a value in an inappropriate way.
non-iterable properties
This problem will be reported when for...of
the value on the right side is not an iterable value, or when it is used as an array destructuring assignment.
For example:
const myobj = { arrayOrObjProp1 : {}, arrayOrObjProp2 : [ 42 ] }; const { arrayOrObjProp1 : [value1], arrayOrObjProp2 : [value2], } = myobj; // TypeError: object is not iterable const obj = { France : "Paris" , England : "London" }; for ( const p of obj) { // … } // TypeError: obj is not iterable
There are built-in iterable objects in JS, such as: String
, Array
, TypedArray
, Map
, Set
and Intl.Segments (en-US)
, because each of their prototype
objects implements @@iterator
the method.
Object
are not iterable unless they implement the iteration protocol.
Simply put, there is an iterable property missing in the object: next
function
Modify the above obj
:
const obj = { France : "Paris" , England : "London" , [ Symbol . iterator ]() { // Use native empty array iterator to be compatible with return [][ Symbol . iterator ](); }, }; for ( const p of obj) { // … }
In this way, no error will be reported, but it will not enter the loop.
Click here to see what is an iteration protocol
Null value problem
null . foo ; // Error type: null does not have this attribute undefined . bar ; // Error type: undefined does not have this attribute const foo = undefined ; foo. substring ( 1 ); // TypeError: foo is undefined
Although it seems simple, it is one of the most frequent reasons for white screen errors.
In the past we usually solved the problem like this:
var value = null ; value && value. foo ;
Now we can use Optional chaining to solve this problem
var value = null ; value? .foo ; // But it cannot be used for assignment: value?. foo = 1
Optional chain syntax:
obj. val ?. prop obj. val ?.[expr] obj. func ?.(args)
Wrong function execution
Wrong function name:
var x = document . getElementByID ( "foo" ); // TypeError: document.getElementByID is not a function var x = document . getElementById ( "foo" ); // Correct function
Function that does not exist:
var obj = { a : 13 , b : 37 , c : 42 }; obj.map ( function ( num ) { return num * 2 ; }); // TypeError: obj.map is not a function
in
error scenario
When judging whether a certain value exists in an object, a common method is to use in
to judge:
var foo = { baz : "bar" }; if ( 'baz' in foo){ // operation }
Because the specific value of foo[‘baz’] cannot be determined, this solution is also good, but when foo
the type cannot be confirmed, errors will easily occur.
var foo = null ; "bar" in foo; // TypeError: invalid 'in' operand "foo" "Hello" in "Hello World" ; // TypeError: invalid 'in' operand "Hello World"
Strings and null values are not suitable for this syntax
_Another thing to note is_, which needs to be used with caution in arrays
const number = [ 2 , 3 , 4 , 5 ]; 3 in number // Returns true. 2 in number // Returns true. 5 in number // Returns false because 5 is not an existing index on the array, but a value;
summary
Because errors follow different value types, and we cannot have 100% control over the reception/transformation of data.
It is the most common type of error we usually report online, and it is also the most likely to cause a white screen on the page. Need to stay 120% careful.
RangeError
RangeError
Object represents an error that a specific value is not in the allowed range or set.
You may encounter this problem in the following situations:
- pass a disallowed string value to
String.prototype.normalize()
, or - Try to use
Array
the constructor to create a string with an illegal length, or - Pass error values to numeric calculation methods (
Number.toExponential()
,Number.toFixed()
orNumber.toPrecision()
).
Here are a few examples:
String . fromCodePoint ( "_" ); // RangeError new Array (- 1 ); // RangeError new Date ( "2014-25-23" ). toISOString (); // RangeError ( 2.34 ). toFixed (- 100 ); // RangeError ( 42 ). toString ( 1 ); const b = BigInt ( NaN ); // RangeError: NaN cannot be converted to a BigInt because it is not an integer
Generally speaking, RangeError is caused by incorrect values being passed in. The probability of this happening is small. Some numbers can be manually controlled or hard-coded in the code
unless they are highly customized. In situations, such as low code, when users are allowed to input at will, it is best to make a judgment first or addtry...catch
ReferenceError
ReferenceError
(ReferenceError) object represents an error that occurs when a variable that does not exist (or has not been initialized) is referenced.
Most of the scenarios where this kind of error is reported are in strict mode. Under normal circumstances, the error “variable is not defined” occurs more frequently.
foo. substring ( 1 ); // ReferenceError: foo is not defined
As above, foo
if it is used directly without being defined, an error will occur.
Another type of error reporting is a problem of assignment. For example, the optional chain function mentioned above cannot be assigned a value:
foo? .bar = 123
This type of coding is easy to analyze and can usually be easily found in the editor, so it does not cause a lot of trouble.
other
InternalError
Object represents errors that occur within the JavaScript engine. It’s not part of any specification yet, so we can ignore it.
EvalError
Represents an eval()
error regarding a global function.
It is not used in the current ECMAScript
specification and therefore will not be thrown by the runtime. But the object itself remains backwards compatible with earlier versions of the specification.
URIError
Object used to represent errors caused by using global URI handlers in an incorrect way.
For example:
decodeURIComponent ( '%' ) // caught URIError: URI malformed decodeURI ( "%" ) // Uncaught URIError: URI malformed at decodeURI
Therefore, when using decodeURIComponent
the function, you need to add try...catch
to maintain correctness
alternative error
unhandledrejection
When Promise
it is rejected and there is no reject handler, unhandledrejection
the event will be triggered;
at this time, an error will be reported: unhanled rejection;
there is no stack information, and you can only rely on the behavior trace to locate the timing of the error.
window . addEventListener ( 'unhandledrejection' , event => { console . log ( 'unhandledrejection: ' , event. reason ); // print }); let p = Promise . reject ( "oops" ); // print unhandledrejection: oops // caught (in promise) oops
Throw errors manually
When we write a third-party library, we can manually throw errors. However, throw error will block the program from running, so please use it with caution.
throw new Error ( "Something went wrong!" ); // caught Error: Something went wrong! throw new RangeError ( "An error occurred. The variable is outside the valid range!" ); throw new TypeError ( "An error occurred. The variable type is invalid!" );
Similarly, we can use this solution Promise
in then
:
// Simulate the return Promise of an interface . resolve ({ code : 3000 , message : 'This is an error!' }). then ( res => { if (res. code !== 200 ) { throw new Error ( ` code 3000: ${res.message} ` ) } console . log (res); // This can be seen as performing normal operations. When an error is thrown, it will not be executed here }). catch ( err => { alert (err. message ) });
In catch
, we can name
judge different ones by Error
:
try { throw new TypeError ( `This is an Error` ) } catch (e) { console . log (e. name ); // TypeError }
Coupled with customization Error
, we can create more free error messages:
class ValidationError extends Error { constructor ( message ) { super (message); this . name = "ValidationError" ; } } try { throw new ValidationError ( `This is an Error` ) } catch (e) { console . log (e. name ); // 'ValidationError' if (e instanceof ValidationError ) { alert ( "Invalid data: " + e. message ); // Invalid data: This is an Error } }
On Error
the basis of , we can also do deeper inheritance to make more customizationsError
The impact of error reporting in react
react
According to the location, I divide the error reports into two categories, one is the rendering error , the other is the execution error ;
rendering is render
the view rendering error in the function, and the other is the execution function error;
The execution error of the function will not affect the rendering of the view, that is, a white screen , but it will have some adverse effects, such as
- Code execution is suspended, part of the logic is not executed, and the overall logic cannot be closed. For example, clicking a button keeps getting stuck
loading
. - There is an exception in the rendering of data, and the data on both sides does not match.
In view rendering (including function return
), triggering JS errors will cause rendering problems.
So why is the entire page blank?
The reason is that React 16
starting from , any error not caught by an error boundaryReact
will cause the entire component tree to be unloaded.
error bounds
This lifecycle exists in react componentDidCatch
and is called after a child component throws an error.
class ErrorBoundary extends React.Component { constructor ( props ) { super (props); this . state = { hasError : false }; } // The latest official recommendation, use this api to get whether an error is triggered static getDerivedStateFromError ( error ) { return { hasError : true }; } // The old solution is here setState componentDidCatch ( error, info ) { // Example "componentStack": // in ComponentThatThrows (created by App) // in ErrorBoundary (created by App) // in div (created by App) // in App logComponentStackToMyService (info. componentStack ); } render () { if ( this . state . hasError ) { return < h1 > Something went wrong. </ h1 > ; } return this . props . children ; } }
< ErrorBoundary fallback = { < p > Something went wrong </ p > }> < Profile /> </ ErrorBoundary >
This is a simple example from the official website. It can cover the error situation of sub-components to avoid affecting the own components or sibling components. The granularity of error boundary components needs to be defined by the developers themselves.
Downgrades and circuit breakers
In the official documentation, he recommends this component react-error-boundary , which has richer uses:
It can simply display errors:
function Fallback({ error }) { return ( < div role = "alert" > < p > Something went wrong: </ p > < pre style = {{ color: "red" }} > {error.message} </ pre > </ div > ); } < ErrorBoundary FallbackComponent = {Fallback} > < ExampleApplication /> </ ErrorBoundary > ;
A reset scheme can also be used :
function Fallback ( { error, resetErrorBoundary } ) { return ( < div role = "alert" > < p > Something went wrong: </ p > < pre style = {{ color: " red " }}> {error.message} </ pre > < button onclick = {resetErrorBoundary} > </ button > </ div > ); }
Resetting components through this method avoids refreshing the page and is more user-friendly.
For more usage, check out
Summarize
There are many errors in JS, but the editor/compiler has helped us filter out most of the errors, but there will still be some errors that will appear under special conditions,
so on the one hand, sufficient testing is required, such as maximum/minimum/ Special values, etc. On the other hand , it is necessary to accumulate experience. Some writing methods are prone to problems. Some problems can be preventedcodeReview
through , services, interfaces, return values, machines, frameworks, middleware, etc. are all regarded as untrustworthy, and every step is carefully guarded.overly pessimistic