Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to implement error handling in JavaScript

2025-03-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)05/31 Report--

In this article, the editor introduces in detail "how to achieve error handling in JavaScript". The content is detailed, the steps are clear, and the details are handled properly. I hope this article "how to achieve error handling in JavaScript" can help you solve your doubts.

Use Promise to handle errors

To demonstrate how Promise is handled, let's go back to the initial example:

Function toUppercase (string) {if (typeof string! = = "string") {throw TypeError ("Wrong type given, expected a string");} return string.toUpperCase ();} toUppercase (4)

Relatively simple to throw an exception, we can use Promise.reject and Promise.resolve:

Function toUppercase (string) {if (typeof string! = = "string") {return Promise.reject (TypeError ("Wrong type given, expected a string"));} const result = string.toUpperCase (); return Promise.resolve (result);}

Because Promise is used, you can use then to receive the returned content, or catch to catch errors that occur.

ToUppercase (99) .then (result = > result) .catch (error = > console.error (error.message))

The result of the above execution:

Wrong type given, expected a string

In addition to then and catch, there is a finally method in Promise, which is similar to finally in try/catch.

ToUppercase (99) .then (result = > result) .catch (error = > console.error (error.message)) .finally () = > console.log ("Run baby, run"))

Promise, error, and throw

Using Promise.reject, you can easily throw an error:

Promise.reject (TypeError ("Wrong type given, expected a string"))

In addition to Promise.reject, we can also exit Promise by throwing an exception.

Consider the following example:

Promise.resolve ("A string") .then (value = > {if (typeof value = = "string") {throw TypeError ("Expected a number!");}})

To stop exception propagation, we use catch as usual:

Promise.resolve ("A string") .then (value = > {if (typeof value = "string") {throw TypeError ("Expected a number!");}}) .catch (reason = > console.log (reason.message))

This pattern is common in fetch:

Fetch ("https://example-dev/api/") .then (response = > {if (! response.ok) {throw Error (response.statusText);} return response.json ();}) .then (json = > console.log (json))

Catch can be used here to intercept exceptions. If we fail, or decide not to catch it, the exception can bubble freely in the stack.

Use Promise to handle exceptions in timers

Exceptions thrown from callbacks cannot be caught using timers or events.

Function failAfterOneSecond () {setTimeout (() = > {throw Error ("Something went wrong!");}, 1000);} / / DOES NOT WORK try {failAfterOneSecond ();} catch (error) {console.error (error.message);}

The solution is to use Promise:

Function failAfterOneSecond () {return new Promise ((_, reject) = > {setTimeout (()) = > {reject (Error ("Something went wrong!"));}, 1000);});}

Using reject, we start a Promise reject, which carries an error object.

At this point, we can use catch to handle exceptions:

FailAfterOneSecond () .catch (reason = > console.error (reason.message))

Use Promise.all to handle errors

The Promise.all (iterable) method returns a Promise instance, which is callback completed (resolve) when all promise in the iterable parameter are "resolved" or if the parameter does not contain promise.

Const promise1 = Promise.resolve ("All good!"); const promise2 = Promise.resolve ("All good here too!"); Promise.all ([promise1, promise2]). Then ((results) = > console.log (results)); / / ['All goodwill gifts,' All good here toodies']

If the promise has a rejected in the parameter, the callback of this instance fails (reject). The reason for the failure is the result of the first failed promise.

Const promise1 = Promise.resolve ("All good!"); const promise2 = Promise.reject (Error ("No good, sorry!")); const promise3 = Promise.reject (Error ("Bad day...")); Promise.all ([promise1, promise2, promise3]) .then (results = > console.log (results)) .catch (error = > console.error (error.message); / / No good, sorry!

Similarly, regardless of how the function runs as a result of Promise.all, finally is executed:

Promise.all ([promise1, promise2, promise3]) .then (results = > console.log (results)) .catch (error = > console.error (error.message)) .finally (() = > console.log ("Always runs!"))

Use Promise.any to handle errors

Promise.any () (Firefox > 79, Chrome > 85) receives an Promise iterable object and returns the successful promise as long as one of the promise succeeds. If none of the promise in the iterable object succeeds (that is, all promises fail / reject), an instance of the failed promise and AggregateError types is returned, which is a subclass of Error and is used to group single errors together. In essence, this method is the opposite of Promise.all ().

Const promise1 = Promise.reject (Error ("No good, sorry!"); const promise2 = Promise.reject (Error ("Bad day...")); Promise.any ([promise1, promise2]) .then (result = > console.log (result)) .catch (error = > console.error (error)) .finally (() = > console.log ("Always runs!"))

Here, we use catch to handle the error, with the output as follows:

AggregateError: No Promise in Promise.any was resolved Always runs!

The AggregateError object has the same properties as the base Error, plus the errors property:

Catch (error = > console.error (catch)) / /

This property is an array of each individual error generated by reject

[Error: "No good, Sorry, Error:" Bad day... "]

Use Promise.race to handle errors

The Promise.race (iterable) method returns a promise, and once a promise in the iterator is resolved or rejected, the returned promise is resolved or rejected.

Const promise1 = Promise.resolve ("The first!"); const promise2 = Promise.resolve ("The second!"); Promise.race ([promise1, promise2]) .then (result = > console.log (result)); / / The first!

It is explained here that the first Promise is more finished than the second line. What about the situation that includes rejection?

Const promise1 = Promise.resolve ("The first!"); const rejection = Promise.reject (Error ("Ouch!")); const promise2 = Promise.resolve ("The second!"); Promise.race ([promise1, rejection, promise2]) .then (result = > console.log (result)); / / The first!

What happens if you put reject first?

Const promise1 = Promise.resolve ("The first!"); const rejection = Promise.reject (Error ("Ouch!")); const promise2 = Promise.resolve ("The second!"); Promise.race ([rejection, promise1, promise2]) .then (result = > console.log (result)) .catch (error = > console.error (error.message)); / / Ouch!

Use Promise.allSettled to handle errors

The Promise.allSettled () method returns a promise after all given promise have been fulfilled or rejected, with an array of objects, each representing the corresponding promise result.

Consider the following example:

Const promise1 = Promise.resolve ("Good!"); const promise2 = Promise.reject (Error ("No good, sorry!"); Promise.allSettled ([promise1, promise2]) .then (results = > console.log (results)) .catch (error = > console.error (error)) .finally () = > console.log ("Always runs!"))

We pass Promise.allSettled an array of two Promise: one resolved and the other rejected.

In this case, catch will not be executed, and finally will always be executed.

[{status: 'fulfilled', value:' goodie'}, {status: 'rejected', reason: Error: No good, sorry!}]

Use async/await to handle errors

For simplicity, we use the previous synchronous function toUppercase and convert it to an asynchronous function by placing async before the function keyword

Async function toUppercase (string) {if (typeof string! = = "string") {throw TypeError ("Wrong type given, expected a string");} return string.toUpperCase ();}

As long as you precede the function with async, the function returns a Promise. This means that we can perform then, catch and finally operations after the function call

Async function toUppercase (string) {if (typeof string! = = "string") {throw TypeError ("Wrong type given, expected a string");} return string.toUpperCase ();} toUppercase ("abc") .then (result = > console.log (result)) .catch (error = > console.error (error.message)) .finally (() = > console.log ("Always runs!"))

When an exception is thrown from the async function, we can use catch to catch it.

Most importantly, in addition to this, we can also use try/catch/finally, just as we do with synchronization functions.

Async function toUppercase (string) {if (typeof string! = = "string") {throw TypeError ("Wrong type given, expected a string");} return string.toUpperCase ();} async function consumer () {try {await toUppercase (98);} catch (error) {console.error (error.message);} finally {console.log ("Always runs!");}} consumer ()

Output:

Wrong type given, expected a string Always runs!

Use async generators to handle errors

Async generators in JavaScript is a generator function that can generate Promises instead of simple values.

Async function* asyncGenerator () {yield 33; yield 99; throw Error ("Something went wrong!"); / / Promise.reject}

Based on Promise, this applies to the same rules for error handling. In the asynchronous generator, throw will trigger the reject of Promise, which we can intercept with catch.

To use the Promise of an asynchronous generator, we can do this:

Then method

Asynchronous traversal

We know from the above that after two calls to yield, the next time an exception is thrown:

Const go = asyncGenerator (); go.next (). Then (value = > console.log (value)); go.next (). Then (value = > console.log (value)); go.next (). Catch (reason = > console.error (reason.message))

Output result:

{value: 33, done: false} {value: 99, done: false} Something went wrong!

The other is to use asynchronous traversal and for await...of:

Async function* asyncGenerator () {yield 33; yield 99; throw Error ("Something went wrong!"); / / Promise.reject} async function consumer () {for await (const value of asyncGenerator ()) {console.log (value);}} consumer ()

With async/await, we can use try/catch to catch exceptions:

Async function* asyncGenerator () {yield 33; yield 99; throw Error ("Something went wrong!"); / / Promise.reject} async function consumer () {try {for await (const value of asyncGenerator ()) {console.log (value);}} catch (error) {console.error (error.message);}} consumer ()

Output result:

33 99 Something went wrong!

The iterator object returned from the asynchronous generator function also has a throw () method, which is very similar to its synchronous copy. Calling throw () on the iterator object here will not throw an exception, but will be rejected by Promise

Async function* asyncGenerator () {yield 33; yield 99; yield 11;} const go = asyncGenerator (); go.next (). Then (value = > console.log (value)); go.next (). Then (value = > console.log (value)); go.throw (Error ("Let's reject!")); go.next (). Then (value = > console.log (value)); / / value is undefined

To deal with this situation externally, we can do:

Go.throw (Error ("Let's reject!")) .catch (reason = > console.error (reason.message))

Error handling in Node

Synchronization error handling in Node

The handling of synchronization errors in Node.js is not much different from what you have seen so far. For synchronization, you can work well with try/catch/finally.

Asynchronous error handling in Node.js: callback mode

For asynchronous code, Node.js mainly uses these two ways:

Callback mode

Event emitters

In callback mode, the asynchronous Node.js API accepts a function that is processed through an event loop and executed immediately when the call stack is empty.

Consider the following code:

Const {readFile} = require ("fs"); function readDataset (path) {readFile (path, {encoding: "utf8"}, function (error, data) {if (error) console.error (error); / / do stuff with the data});}

As we can see, the way to handle errors here is to use callbacks:

/ / function (error, data) {if (error) console.error (error); / / do stuff with the data} / /

If we use fs.readFile to read a given path and cause any errors, we get an error object.

At this point, we can:

Simply type out the object error.

Throw an error

Pass the error to another callback

We can throw an exception.

Const {readFile} = require ("fs"); function readDataset (path) {readFile (path, {encoding: "utf8"}, function (error, data) {if (error) throw Error (error.message); / / do stuff with the data});}

However, like events and timers in DOM, this exception crashes the program. Capturing it through try/catch does not work:

Const {readFile} = require ("fs"); function readDataset (path) {readFile (path, {encoding: "utf8"}, function (error, data) {if (error) throw Error (error.message); / / do stuff with the data});} try {readDataset ("not-here.txt");} catch (error) {console.error (error.message);}

If we don't want to crash the program, passing the error to another callback is the preferred method:

Const {readFile} = require ("fs"); function readDataset (path) {readFile (path, {encoding: "utf8"}, function (error, data) {if (error) return errorHandler (error); / / do stuff with the data});}

The errorHandler here, as its name implies, is a simple function for error handling:

Function errorHandler (error) {console.error (error.message); / / do something with the error: / /-write to a log. / /-send to an external logger. }

Asynchronous error handling in Node.js: event emitters

Most of the work done in Node.js is event-based. In most cases, emitter object interacts with some observers to listen for messages.

Any event-driven module in Node.js, such as net, extends a root class called EventEmitter.

There are two basic methods for EventEmitter in Node.js: on and emit.

Consider the following simple HTTP server:

Const net = require ("net"); const server = net.createServer (). Listen (8081, "127.0.0.1"); server.on ("listening", function () {console.log ("Server listening!");}); server.on ("connection", function (socket) {console.log ("Client connected!"); socket.end ("Hello client!");})

Here we listen to two events: listening and connection. In addition to these events, event emitters exposes an error event to prevent errors.

If you run this code on port 80 instead of listening on the previous example, you will get an exception:

Const net = require ("net"); const server = net.createServer (). Listen (80, "127.0.0.1"); server.on ("listening", function () {console.log ("Server listening!");}); server.on ("connection", function (socket) {console.log ("Client connected!"); socket.end ("Hello client!");})

Output:

Events.js:291 throw er; / / Unhandled 'error' event ^ Error: listen EACCES: permission denied 127.0.0.1 events.js:291 throw er; 80 Emitted' error' event on Server instance at:.

To capture it, we can register an error event handler:

Server.on ("error", function (error) {console.error (error.message);})

Output result:

Listen EACCES: permission denied 127.0.0.1 JavaScript 80 read here, this article "how to implement error handling in JavaScript" has been introduced. If you want to master the knowledge points of this article, you still need to practice and use it before you can understand it. If you want to know more about related articles, welcome to follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report