preface

Programming is often presented with correct business documentation or specifications for business processes, but actual development is riddled with thorns and exceptions, including exceptions to business use cases as well as technical exceptions. We have no alternative to exceptions to business use cases, and must require both implementor and user to provide reasonable solutions; The technical exceptions, however, have to be handled by our programmers, and that’s what I want to document.


I’m going to split

Front-end Magic Hall — Exceptions are more than just try/ Catch

And “Front-end Magic: Call Stack, Treasure of Exception Instances” describe built-in/custom exception classes, capturing runtime/syntax/network request exceptions /PromiseRejection events, what a call stack is, and how to get the call stack.


Are you looking forward to it even before you start? Ok, everybody hold on to the handrail, the old driver is going to drive

The profile

This article will describe the following contents:

  • Exception or error? How will it affect our code?
  • What are the built-in exception types?
  • Start writing your own exception types!
  • Try /catch is enough to catch the runtime exception in synchronized code.
  • The “omnipotent” exception catcher window.onerror, really omnipotent?
  • Promise. Reject Also throws exceptions, what to do?
  • 404, such as network request abnormality really after sleep?


One. Exception or error? How will it affect our code?

When we learn Java, we are told that exceptions are different from errors. Exceptions do not cause the process to terminate and can be fixed (try/catch), but errors cause the process to terminate and cannot be fixed. When it comes to JavaScript, all we have to deal with is an exception (although the exception class name is Error or contains the Error word). The occurrence of an exception does not cause the JavaScript engine to crash, but only terminates the currently executing task.


What do you mean by saying that an exception can only cause the current task to terminate? This involves the principle of Event Loop, and I will try to explain it in code.

<script>

// 1. The current code block will be pushed into the task queue as a task, and the JavaScript thread will continuously extract the task from the task queue for execution; // 2. If an exception is reported during the execution of the task, and the exception is not captured and processed, the call stack will be thrown from the top to the bottom, and the execution of the current task will be terminated. // 3. The JavaScript thread will continue to extract the next task from the task queue and continue to execute. Function a(){throw Error(“test”)} function b(){a()} b() console.log(” never executed! “) )

</script>
<script>

// Next task console.log(” You have your exception, I still execute!” )

</script>

What are the built-in exception types?

When it comes to built-in exception classes, the ancestor of Error must be mentioned first. All other built-in and custom classes must inherit from Error. These are just a few of its standard properties and methods

@prop

{String}
name

– Exception name @prop

{String}
message

– Unusual messages for human reading @prop

{Function}

Constructor – constructor @method toString():

String

– Displays abnormal information

Because there were too few standard attributes to provide more effective information for developers to locate exceptions and reconstruct accident scenes, browser manufacturers began adding their own attributes, which gradually became de facto standards.

@

prop

{

String

}

fileName

The script in which the exception occurs

URI

@

prop

{

number

}

lineNumber

The line number on which the exception occurred @

prop

{

number

}

columnNumber

The column number where the exception occurred @

prop

{

String

}

stack

Call stack information when an exception occurs,

IE10

@ is supported only when above

method

ToSource ():String – The content of the script where the exception occurred

Additional giant hard still add the following two attributes

@

prop

{

String

}

description

message

Almost @

prop

{

number

}

number

The number of the exception type. Jumbo sets a unique number for each exception

So now I want to instantiate an Error object, just call Error() or new Error(); If you want to set message at the same time, change to Error(“test”) or new Error(“test”). The Error constructor signature actually looks like this

@constructor@param {String=} message – Set the message attribute @param {String=} fileName – Set the fileName attribute @param {number=} lineNumber – Set the lineNUmber property

Now let’s take a look at what types of exceptions are built in!

  • EvalError, an exception that occurs when eval() is called, has been deprecated for backward compatibility only
  • InternalError, JavaScript engine internal exception, FireFox only provided!
  • RangeError, when crossing the line function arguments to occur, such as Array Number. ToExponential, Number. ToFixed and Number toPrecision into illegal refs.
  • ReferenceError occurs when an undeclared variable is referenced
  • SyntaxError, a SyntaxError occurred during parsing
  • TypeError, null.f() also reports this error when the value is not of the expected type
  • URIError, when passing a illegal URI to global URI processing function, such as decodeURIComponent (‘ % ‘), namely decodeURIComponent, decodeURI, encodeURIComponent, encodeURI

Write your own exception types!

There’s been a lot of discussion on StackOverflow about how to customize exception types

reference


So we can just pick it up

function MyError(message, fileName, lineNumber){

if

(

this
instanceof

MyError);

else
return
new

MyError(message, fileName, lineNumber)

this

.message = message ||

“”
if

(fileName){

this

.fileName = fileName }

if

(lineNumber){

this

.lineNumber = lineNumber }}

var

proto = MyError.prototype =

Object

.create(

Error

.prototype)proto.name =

“MyError”

proto.constructor = MyError

The CLJS implementation is as follows

(

defn
^export

MyError [& args] (

this-as

this (

if

(

instance?

MyError this) (

let

[ps [

“message”
“fileName”
“lineNumber”

] idxs (

->

(

min

(

count

args) (

count

ps)) range)] (

reduce

(

fn

[accu i] (

aset

accu (

nth

ps i) (

nth

args i)) accu) this idxs)) (

apply

new MyError args))))(

def

proto (

aset

MyError

“prototype”

(

.create

js/Object (

.-prototype

Error))))(

aset

proto

“name”
“MyError”

) (

aset

proto

“constructor”

MyError) four. Try /catch is enough to catch the runtime exception in synchronized code

To avoid the risk of normal code being skipped due to an exception, try/catch is used to catch and handle exceptions.

try

{

throw
Error

(

“unexpected operation happen…”

)}

catch

(e){

console

.log(e.message)}

CLJS writing

(

try

(

throw

(

Error.
“unexpected operation happen…”

) (

catch

e (

println

(

.-message

e)))))

Most of the time we would think that writing would be done, but try/catch can only catch “runtime exceptions” in “synchronized code.”


1.” Synchronous code “means that it cannot get exceptions from asynchronous code such as setTimeout and Promise, that is, try/catch can only catch exceptions from the current task, and asynchronous code such as setTimeout is executed in the next EventLoop.

// True capture can not ah pro ~!
try

{ setTimeout(function(){

throw
Error

(

“unexpected operation happen…”

)}, 0)}

catch

(e){

console

.log(e)}

2.” runtime exception “refers to a non-syntaxerror, which is a SyntaxError that cannot be caught because it was reported when parsing JavaScript source code

// invalid identifier a->b
try

{ a->b = 1}

catch

(e){

console

.log(e)}

It’s tempting to ask, “What about asynchronous code exceptions? What about syntax exceptions?” Before we answer that question, let’s deviate a little and dig a little deeper into the nature of the throw statement.

What can be followed by a throw?

In general we throw an instance of Error or a subclass of Error(such as throw Error()), but we throw any type of data (such as throw 1,throw “test”,throw true, etc.). But even though we can throw arbitrary types of data, we insist on throwing instances of Error or its subclasses. Why is that?

try

{

throw
“unexpected operation happen…”

}

catch

(e){

console

.log(e)}

try

{

throw
TypeError

(

“unexpected operation happen…”

)}

catch

(e){

if

(

“TypeError”

== e.name){

// Do something1

}

else
if

(

“RangeError”

== e.name){

// Do something2

}}

The reason is obvious – the more complete information you provide when an exception occurs, the easier it is to track down and locate the problem.

Window. onerror is a universal exception catcher.

It is obviously not practical (and there are performance issues) to write try/catch everywhere an exception can occur, even if it is verbose like Java, where we constantly declare throws and then handle exceptions at the top level. So where is the corresponding top-level exception handling entry in JavaScript? There is no mistake, just window.onerror. Look at the method signature

@

description

Window. onerror @param {

string

}

message

Exception message “@

param

{

string

}

source

Of the script in which the exception occurred

URI

@

param

{

number

}

lineno

The script number on which the exception occurred @

param

{

number

}

colno

The script column where the exception occurred @

param

{?

Error

}

error
Error

Instance,

Safari

and

IE10

Does not have this argument in

At this point we can catch through it in addition to try/catch can catch exceptions, but also catch setTimeout and other asynchronous code exceptions, syntax errors.

window

.onerror = function(message, source, lineno, colno, error){

// Do something you like.

}setTimeout(function(){

throw
Error

(

“oh no!”

) }, 0)a->b = 1

Is that enough? Yet to play a big game – blocking exceptions, shielding, screen ~ ~


If onError returns true, the exception will not continue to be thrown up (otherwise it will become an Uncaught Error).

// there is no problem with exception, because I can’t see ^_^
window

.onerror = function(){

return
true

}

Now back to the question of the title, is onError enough to catch all exceptions? The answer is no (oh my god, how much longer are we going to do this ~ 0 ~)

  • For exceptions reported by cross-domain scripts in Chrome, although onError can catch them, Script Error is reported uniformly. To get the correct error information, cross-domain resource sharing CORS must be configured.
  • Window.onerror actually uses the event bubbling mechanism to catch exceptions and is only raised during the bubble phase, so non-bubbling exceptions such as network request exceptions cannot be caught.
  • Window.onerror cannot handle exceptions that Promise. Reject generates that are not caught.

Reject also throw exception, how to do?

Dealing with complex asynchronous process control through Promises is handy, but what if there is an exception or the state of the Promise instance changes to Rejected?

How does a Promise signal that an exception has occurred?

The initial state of the Promise instance is Pending and the exception is Rejected. The action that causes the state to change from pending to Rejected is

  • Call the promise.reject class method
  • Call the Reject method in the factory method
  • Throw an exception in a factory method or then callback function
1 / / way
Promise

.reject(

“anything you want”

)

2 / / way
new
Promise

(function(resolve, reject) { reject(

“anything you want”

)})

3 / / way
new
Promise

(function{

throw
“anything you want”

})

new
Promise

(function(r) { r(

Error

(

“anything you want”

) }).then(function(e) {

throw

e })

When a Promise instance changes from Pending to Rejected, it is either caught and processed or it continues to be thrown until it becomes an Uncaught(in Promise) Error.

Catch exceptions before they happen

If we had called the catch method to catch the exception before it happened, we would be fine

new
Promise

(function(resolve, reject){ setTimeout(reject, 0)}).catch(function(e){

console

.log(

“catch”

)

return
“bingo”

}).then(function(x){

console

.log(x)})

/ / echo bingo

Top-level exception handling that is Promise specific

If we do not call the catch method before the exception occurs, we can still catch the exception through the unhandledrejection event of the window

window

.addEventListener(

“unhandledrejection”

, function(e){

// Event adds a new attribute
// @prop {Promise} Promise – The Promise instance whose state is Rejected
/ / @ prop {String | Object} “reason – the content of the anomaly information or rejected
// Will prevent the exception from continuing to be thrown, so that Uncaught(in promise) Error does not occur

E.preventdefault ()}) a late catch

Since a Promise instance can subscribe asynchronously to its state changes, that is, it can register a catch handler asynchronously, we have already thrown an Uncaught(in Promise) Error, but we can still handle it

var

p =

new
Promise

(function(resolve, reject){ setTimeout(reject, 0)})setTimeout(function(){ p.catch(function(e){

console

.log(

“catch”

)

return
“bingo”

})}, 1000).

Alternatively, you can listen for the asynchronous registration of a catch handler through the RejectionHandled event of the window

window

.addEventListener(

“rejectionhandled”

, function(e){

// Event adds a new attribute
// @prop {Promise} Promise – The Promise instance whose state is Rejected
/ / @ prop {String | Object} “reason – the content of the anomaly information or rejected
// Uncaught(in promise) Error has been thrown, so this sentence does not mean anything

e.preventDefault()})

Note: An asynchronous catch will only raise this event if an Uncaught(in Promise) Error is thrown.

Seven.404, such as abnormal network request really after sleep?



window

.addEventListener(

“error”

, function(e){

// Do something
console

.log(e.bubbles)

/ / echo false

},

true

)

Because network request exceptions do not bubble up, they must be caught during the Capture phase. However, another problem is that this method can not accurately determine whether the HTTP status of the exception is 404 or 500, so it still needs to be analyzed with the server log.

conclusion

Exceptions and how to catch them are just a handful of tips on front-end intelligence monitoring. Stay up for another handful of tips on front-end magic: Call Stack, Treasure of Exception Instances 😀


Please note:
www.cnblogs.com/fsjohnhuang…^_^ fat John

reference

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError



stackoverflow.com/questi … …


Reprinted from ^_^ fat boy John

Link address: www.cnblogs.com/fsjohnhuang…

This article is for sharing only, if there is infringement, please contact me to delete