Unlike the catchblock, a finallyblock does not receive an error object as a parameter, so it operates very much in the dark about what transpires inside the tryblock.. In the first, the
Trang 1The single catchblock in Listing 39-7 executes only if one of the statements in the tryblock throws an exception The exceptions may be not only one of the four specific ones named in the catchblock but also syntax or other errors that could occur inside the tryblock That’s why you have a last-ditch case to handle truly unexpected errors Your job as scripter is to not only anticipate errors but also to provide clean ways for the exceptions to be handled, whether they be through judi-ciously worded alert dialog boxes or perhaps even some self-repair For example, in the case of the invalid character error for createElement(), your script may attempt to salvage the data passed to the attachToEnd()function and reinvoke the method passing theNodevalue as-is and the repaired value originally passed to
newTag If your repairs were successful, the tryblock would execute without error and carry on with the user’s being completely unaware that a nasty problem had been averted
A finallyblock contains code that always executes after a tryblock, whether
or not the tryblock succeeds without throwing an error Unlike the catchblock, a
finallyblock does not receive an error object as a parameter, so it operates very much in the dark about what transpires inside the tryblock If you include both
catchand finallyblocks after a tryblock, the execution path depends on whether an exception is thrown If no exception is thrown, the finallyblock exe-cutes after the last statement of the tryblock runs But if the tryblock throws an exception, program execution runs first to the catchblock After all processing within the catchblock finishes, the finallyblock executes In development envi-ronments that give programmers complete control over resources, such as memory allocation, a finallyblock may be used to delete some temporary items generated
in the tryblock, whether or not an exception occurs in the tryblock Currently, JavaScript has less need for that kind of maintenance, but you should be aware of the program execution possibilities of the finallyblock in the try-catch-finally
context
Real-life exceptions
The example shown in Listing 39-6 is a bit idealized The listing assumes that the browser dutifully reports every W3C DOM exception precisely as defined in the for-mal specification Unfortunately, that’s not how it is (yet) in browsers through IE5.5 and NN6 Both browsers implement additional error naming conventions and layers between actual DOM exceptions and what gets reported with the error object at the time of the exception
If you think these discrepancies make cross-browser exception handling difficult, you’re right Even simple errors are reported differently among the two major browser brands and the W3C DOM specification Until the browsers exhibit a greater unanimity in exception reporting, the smoothest development road will be for those scripters who have the luxury of writing for one of the browser platforms, such as IE5 for Windows or NN6
That said, however, one aspect of exception handling can still be used in both IE5+ and NN6 You can take advantage of try-catchconstructions to throw your own exceptions — a practice that is quite common in advanced programming environments
try-catch-finally
Trang 2Throwing Exceptions
The last exception handling keyword not covered yet —throw— makes it
possi-ble to utilize exception handling facilities for your own management of processes,
such as data entry validation At any point inside a tryblock, you can manually
throw an exception that gets picked up by the associated catchblock The details
of the specific exception are up to you
Syntax for the throwstatement is as follows:
throw value
The value you throw can be of any type, but good practice suggests that the
value be an error object (described more fully later in this chapter) Whatever
value you throw is assigned to the parameter of the catchblock Look at the
fol-lowing two examples In the first, the value is a string message; in the second, the
value is an error object
Listing 39-8 presents one input text box for a number between 1 and 5 Clicking a
button looks up a corresponding letter in an array and displays the letter in a
sec-ond text box The lookup script has two simple data validation routines to make
sure the entry is a number and is in the desired range Error checking here is done
manually by script If either of the error conditions occurs, throwstatements force
execution to jump to the catchblock The catchblock assigns the incoming
stringparameter to the variable e The design here assumes that the message
being passed is text for an alert dialog box Not only does a single catchblock take
care of both error conditions (and conceivably any others to be added later), but
the catchblock runs within the same variable scope as the function, so that it can
use the reference to the input text box to focus and select the input text if there is
an error
Listing 39-8: Throwing String Exceptions
<HTML>
<HEAD>
<TITLE>Throwing a String Exception</TITLE>
<SCRIPT LANGUAGE=”JavaScript”>
var letters = new Array(“A”,”B”,”C”,”D”,”E”)
function getLetter(fld) {
try {
var inp = parseInt(fld.value, 10)
if (isNaN(inp)) {
throw “Entry was not a number.”
}
if (inp < 1 || inp > 5) {
throw “Enter only 1 through 5.”
}
fld.form.output.value = letters[inp]
}
catch (e) {
alert(e)
fld.form.output.value = “”
Trang 3Listing 39-8 (continued)
fld.focus() fld.select() }
}
</SCRIPT>
</HEAD>
<BODY>
<H1>Throwing a String Exception</H1>
<HR>
<FORM>
Enter a number from 1 to 5:
<INPUT TYPE=”text” NAME=”input” SIZE=5>
<INPUT TYPE=”button” VALUE=”Get Letter” onClick=getLetter(this.form.input)> Matching Letter is:<INPUT TYPE=”text” NAME=”output” SIZE=5>
</FORM>
</BODY>
</HTML>
The flaw with Listing 39-8 is that if some other kind of exception were thrown inside the tryblock, the value passed to the catchblock would be an error object, not a string The alert dialog box displayed to the user would be meaningless Therefore, it is better to be uniform in your throw-catchconstructions and pass an error object
Listing 39-9 is an updated version of Listing 39-8, demonstrating how to create an error object that gets sent to the catchblock via throwstatements The one glitch
in generating an error object comes in IE5 and IE5.5 The ECMA-262 standard allows
a script statement to set the messageproperty of an error object to directly by passing a string as the parameter to the new Error()constructor This is how NN6 works But the error object in IE5 does not have the messageproperty at all, and in IE5.5, the parameter is not assigned to the messageproperty Therefore, Listing 39-9 contains a separate utility function (getErrorObj()) that fills the gap when an error object does not have the messageproperty to begin with or doesn’t have the property set automatically If a future version of IE adopts the ECMA standard way, then the extra branch is avoided, just as it is for NN6
Listing 39-9: Throwing an Error Object Exception
<HTML>
<HEAD>
<TITLE>Throwing an Error Object Exception</TITLE>
<SCRIPT LANGUAGE=”JavaScript”>
var letters = new Array(“A”,”B”,”C”,”D”,”E”) function getErrorObj(msg) {
var err = new Error(msg) // take care of IE5/5.5
if (!err.message) {
throw
Trang 4err.message = msg
}
return err
}
function getLetter(fld) {
try {
var inp = parseInt(fld.value, 10)
if (isNaN(inp)) {
throw getErrorObj(“Entry was not a number.”)
}
if (inp < 1 || inp > 5) {
throw getErrorObj(“Enter only 1 through 5.”)
}
fld.form.output.value = letters[inp]
}
catch (e) {
alert(e.message)
fld.form.output.value = “”
fld.focus()
fld.select()
}
}
</SCRIPT>
</HEAD>
<BODY>
<H1>Throwing an Error Object Exception</H1>
<HR>
<FORM>
Enter a number from 1 to 5:
<INPUT TYPE=”text” NAME=”input” SIZE=5>
<INPUT TYPE=”button” VALUE=”Get Letter” onClick=getLetter(this.form.input)>
Matching Letter is:<INPUT TYPE=”text” NAME=”output” SIZE=5>
</FORM>
</BODY>
</HTML>
The only difference to the catchblock is that it now reads the messageproperty
of the incoming error object This means that if some other exception is thrown
inside the tryblock, the browser-generated message will be displayed in the alert
dialog box
In truth, however, the job really isn’t complete In all likelihood, if a
browser-generated exception is thrown, the message in the alert dialog box won’t mean
much to the user The error message will probably be some kind of syntax or type
error — the kind of meaningless error message you often get from your favorite
operating system A better design is to branch the catchblock so that “intentional”
exceptions thrown by your code are handled through the alert dialog box messages
you’ve put there, but other types are treated differently To accomplish this, you
can take over one of the other properties of the error object —name— so that your
catchblock treats your custom messages separately
Trang 5In Listing 39-10, the getErrorObj()function adds a custom value to the name
property of the newly created error object The name you assign can be any name, but you want to avoid exception names used by JavaScript or the DOM Even if you don’t know what all of those are, you can probably conjure up a suitably unique name for your error Down in the catchblock, a switchconstruction branches to treat the two classes of errors differently Notice that because IE5’s error object does not have a nameproperty, the switchexpression (e.name) evaluates to
undefined, which forces the defaultcase to execute whenever a native exception
is thrown (and you have to be careful about which error object properties you use
in the defaultcase statements) In this simplified example, about the only possi-ble propossi-blem other than the ones being trapped for explicitly in the tryblock would
be some corruption to the page during downloading Therefore, for this example, the branch for all other errors simply asks that the user reload the page and try again The point is, however, that you can have as many classifications of custom and system errors as you want and handle them in a single catch block accordingly
Listing 39-10: A Custom Object Exception
<HTML>
<HEAD>
<TITLE>Throwing a Custom Error Object Exception</TITLE>
<SCRIPT LANGUAGE=”JavaScript”>
var letters = new Array(“A”,”B”,”C”,”D”,”E”) function getErrorObj(msg) {
var err = new Error(msg) // take care of IE5/5.5
if (!err.message) { err.message = msg }
err.name = “MY_ERROR”
return err }
function getLetter(fld) { try {
var inp = parseInt(fld.value, 10)
if (isNaN(inp)) { throw getErrorObj(“Entry was not a number.”) }
if (inp < 1 || inp > 5) { throw getErrorObj(“Enter only 1 through 5.”) }
fld.form.output.value = letters[inp]
} catch (e) { switch (e.name) { case “MY_ERROR” : alert(e.message) fld.form.output.value = “”
fld.focus() fld.select()
throw
Trang 6break default : alert(“Reload the page and try again.”) }
}
}
</SCRIPT>
</HEAD>
<BODY>
<H1>Throwing a Custom Error Object Exception</H1>
<HR>
<FORM>
Enter a number from 1 to 5:
<INPUT TYPE=”text” NAME=”input” SIZE=5>
<INPUT TYPE=”button” VALUE=”Get Letter” onClick=getLetter(this.form.input)>
Matching Letter is:<INPUT TYPE=”text” NAME=”output” SIZE=5>
</FORM>
</BODY>
</HTML>
If you want to see how the alternative branch of Listing 39-10 looks, copy the
list-ing file from the CD-ROM to your hard disk and modify the last line of the tryblock
so that one of the letters is dropped from the name of the array:
fld.form.output.value = letter[inp]
This may simulate the faulty loading of the page If you enter one of the allowable
values, the reload alert appears, rather than the actual message of the error object:
letter is undefined Your users will thank you
All that’s left now on this subject are the details on the error object
Error Object
Properties Methods
errorObject.constructor
errorObject.description
errorObject.filename
errorObject.lineNumber
errorObject.message
errorObject.name
errorObject.number
Trang 7Creating an error object:
var myError = new Error(“message”) var myError = Error(“message”)
Accessing static Errorobject property:
Error.property
Accessing error object properties and methods:
errorObject.property | method([parameters])
About this object
An error object instance is created whenever an exception is thrown or when you invoke either of the constructor formats for creating an error object Properties
of the error object instance contain information about the nature of the error so that catchblocks can inspect the error and process error handling accordingly IE5 implemented an error object in advance of the ECMA-262 formal error object, and the IE5 version ends up having its own set of properties that are not part of the ECMA standard Those proprietary properties are still part of IE5.5, which includes the ECMA properties as well NN6, on the other hand, starts with the ECMA proper-ties and adds two proprietary properproper-ties of its own The browser uses these addi-tional properties in its own script error reporting The unfortunate bottom line for cross-browser developers is that no properties in common among all browsers sup-port the error object However, two common denominators (nameand message) are between IE5.5 and NN6
As described earlier in this chapter, you are encouraged to create an error object whenever you use the throwstatement for your own error control See the discus-sion surrounding Listing 39-9 about handling missing properties in IE
Properties
constructor
See string.constructor(Chapter 34)
description
errorObject.description
Trang 8The descriptionproperty contains a descriptive string that provides some
level of detail about the error For errors thrown by the browser, the description is
the same text that appears in the script error dialog box in IE Although this
prop-erty continues to be supported, the messageproperty in IE5.5 and NN6 is preferred
Related Items:messageproperty
fileName
lineNumber
The NN6 browser uses the fileNameand lineNumberproperties of an error
object for its own internal script error processing — these values appear as part of
the error messages that are listed in the JavaScript Console The fileNameis the
URL of the document causing the error; the lineNumberis the source code line
number of the statement that threw the exception These properties are exposed to
JavaScript, as well, so that your error processing may use this information if it is
meaningful to your application
Both of these properties (along with the messageproperty) have been in the
Navigator vernacular since NN3 See the discussion of the window.errorproperty
in Chapter 16 for further ideas on how to use this information for bug reporting
from users
Related Items:window.errorproperty
message
The messageproperty contains a descriptive string that provides some level of
detail about the error For errors thrown by the browser, the message is the same
text that appears in the script error dialog box in IE and the JavaScript Console in
NN6 By and large, these messages are more meaningful to scripters than to users
Unfortunately, there are no standards for the wording of a message for a given error
Therefore, it is hazardous at best to use the message content in a catchblock as a
means of branching to handle particular kinds of errors You may get by with this
approach if you are developing for a single browser platform, but you have no
assurances that the text of a message for a particular exception may not change in
future browser versions
Trang 9Custom messages for errors that your code explicitly throws can be in user-friendly language if you intend to display such messages to users See Listings 39-8 through 39-10 for examples of this usage
Related Items: description property.
name
The nameproperty generally contains a word that identifies the type of error that has been thrown The most general kind of error (and the one that is created via the new Error()constructor) has a name Error But JavaScript errors can be
of several varieties: EvalError, RangeError, ReferenceError, SyntaxError,
TypeError, and URIError Some of these error types are not necessarily intended for exposure to scripters (they’re used primarily in the inner workings of the JavaScript engine), but some browsers do expose them Unfortunately, there are some discrepancies as to the specific name supplied to this property for script errors
When JavaScript is being used in a browser environment that employs the W3C DOM, some DOM exception types are returned via the nameproperty But browsers frequently insert their own error types for this property, and, as is common in this department, little uniformity exists among browser brands
For custom exceptions that your code explicitly throws, you can assign names as you want As shown in Listings 39-9 and 39-10, this information can assist a catch
block in handling multiple categories of errors
Related Items:messageproperty
number
IE5+ assigns unique numbers to each error description or message The number
property, however, is problematical While Microsoft documents a sequence of syn-tax and runtime errors and their numbers, in practice, IE browsers do not report the numbers shown in Microsoft’s own documentation This is unfortunate, because the number can be a language-independent way of branching catchblock code based on the error number, rather than the description or message And,
errorObject.number
Trang 10because the numberproperty was born at the same time as the description
prop-erty (now superseded by the messageproperty), it is unknown how reliable the
number values (if you can figure them out) will be going forward
Related Items:descriptionproperty
Methods
toString()
Returns: String (see text).
The toString()method for an error object should return a string description of
the error In IE5 and 5.5, however, the method returns a reference to the very same
error object In NN6, the method returns the messageproperty string, preceded by
the string Error:(with a space after the colon) Most typically, if you want to
retrieve a human-readable expression of an error object, read its message(or, in
IE5, description) property
Related Items:messageproperty