error
Table of Contents

Error 错误处理

错误分类

程序逻辑问题

var s = null;
var len = s.length; // TypeError:null变量没有length属性

对于这种错误,要修复程序

执行过程中的错误

程序可能遇到无法预测的异常情况而报错,例如,网络连接中断,读取不存在的文件,没有操作权限等。

对于这种错误,我们需要处理它,并可能需要给用户反馈。

int fd = open("/path/to/file", O_RDONLY);
if (fd == -1) {
    printf("Error when open file!");
} else {
    // TODO
}

通过错误码返回错误,就需要约定什么是正确的返回值,什么是错误的返回值。上面的open()函数约定返回-1表示错误。

显然,这种用错误码表示错误在编写程序时十分不便。

try ... catch ... finally

'use strict';
var r1, r2, s = null;
try {
    r1 = s.length; // 此处应产生错误
    r2 = 100; // 该语句不会执行
} catch (e) {
    console.log('出错了:' + e);
} finally {
    console.log('finally');
}
console.log('r1 = ' + r1); // r1应为undefined
console.log('r2 = ' + r2); // r2应为undefined
>>>
出错了:TypeError: Cannot read property 'length' of null
finally
r1 = undefined
r2 = undefined

当代码块被try { ... }包裹的时候,就表示这部分代码执行过程中可能会发生错误,一旦发生错误,就不再继续执行后续代码,转而跳到catch块。catch (e) { ... }包裹的代码就是错误处理代码,变量e表示捕获到的错误。最后,无论有没有错误,finally一定会被执行。

有错误发生时,执行流程像这样:

  1. 先执行try { ... }的代码;
  2. 执行到出错的语句时,后续语句不再继续执行,转而执行catch (e) { ... }代码;
  3. 最后执行finally { ... }代码。

而没有错误发生时,执行流程像这样:

  1. 先执行try { ... }的代码;
  2. 因为没有出错,catch (e) { ... }代码不会被执行;
  3. 最后执行finally { ... }代码。

最后请注意,catchfinally可以不必都出现。

只有try ... catch,没有finally

try {
    ...
} catch (e) {
    ... //错误处理
}
var txt="";
function message()
{
try
  {
  adddlert("Welcome guest!");
  }
catch(err)
  {
  txt="本页有一个错误。\n\n";
  txt+="错误描述:" + err.message + "\n\n";
  txt+="点击确定继续。\n\n";
  alert(txt);
  }
}

只有try ... finally,没有catch

try {
    ...
} finally {
    ...
}

错误类型

JavaScript有一个标准的Error对象表示错误,还有从Error派生的TypeErrorReferenceError等错误对象。我们在处理错误时,可以通过catch(e)捕获的变量e访问错误对象:

try {
    ...
} catch (e) {
    if (e instanceof TypeError) {
        alert('Type error!');
    } else if (e instanceof Error) {
        alert(e.message);
    } else {
        alert('Error: ' + e);
    }
}

使用变量e是一个习惯用法,也可以以其他变量名命名,如catch(ex)

抛出错误 throw

程序也可以主动抛出一个错误,让执行流程直接跳转到catch块。抛出错误使用throw语句

'use strict';
var r, n, s;
try {
    s = prompt('请输入一个数字');
    n = parseInt(s);
    if (isNaN(n)) {
        throw new Error('输入错误');
    }
    // 计算平方:
    r = n * n;
    console.log(n + ' * ' + n + ' = ' + r);
} catch (e) {
    console.log('出错了:' + e);
}
<!DOCTYPE html>
<html>
<body>

<script>
function myFunction()
{
try
{ 
var x=document.getElementById("demo").value;
if(x=="")    throw "值为空";
if(isNaN(x)) throw "不是数字";
if(x>10)     throw "太大";
if(x<5)      throw "太小";
}
catch(err)
{
var y=document.getElementById("mess");
y.innerHTML="错误:" + err + "。";
}
}
</script>

<h1>我的第一个 JavaScript 程序</h1>
<p>请输入 5 到 10 之间的数字:</p>
<input id="demo" type="text">
<button type="button" onclick="myFunction()">测试输入值</button>
<p id="mess"></p>

</body>
</html>

处理错误

当我们用catch捕获错误时,一定要编写错误处理语句:

var n = 0, s;
try {
    n = s.length;
} catch (e) {
    console.log(e);
}
console.log(n);

哪怕仅仅把错误打印出来,也不要什么也不干:

var n = 0, s;
try {
    n = s.length;
} catch (e) {
}
console.log(n);

因为catch到错误却什么都不执行,就不知道程序执行过程中到底有没有发生错误。

处理错误时,请不要简单粗暴地用alert()把错误显示给用户。

异步错误处理

编写JavaScript代码时,我们要时刻牢记,JavaScript引擎是一个事件驱动的执行引擎,代码总是以单线程执行,而回调函数的执行需要等到下一个满足条件的事件出现后,才会被执行。

例如,setTimeout()函数可以传入回调函数,并在指定若干毫秒后执行:

function printTime() {
    console.log('It is time!');
}

setTimeout(printTime, 1000);
console.log('done');

上面的代码会先打印done,1秒后才会打印It is time!

如果printTime()函数内部发生了错误,我们试图用try包裹setTimeout()是无效的:

'use strict';
function printTime() {
    throw new Error();
}

try {
    setTimeout(printTime, 1000);
    console.log('done');
} catch (e) {
    console.log('error');
}
>>>
done

表单验证

JavaScript 可用来在数据被送往服务器前对 HTML 表单中的这些输入数据进行验证。

被 JavaScript 验证的这些典型的表单数据有:

必填(或必选)项目

下面的函数用来检查用户是否已填写表单中的必填(或必选)项目。假如必填或必选项为空,那么警告框会弹出,并且函数的返回值为 false,否则函数的返回值则为 true(意味着数据没有问题):

function validate_required(field,alerttxt)
{
with (field)
{
if (value==null||value=="")
  {alert(alerttxt);return false}
else {return true}
}
}

下面是连同 HTML 表单的代码:

<html>
<head>
<script type="text/javascript">

function validate_required(field,alerttxt)
{
with (field)
  {
  if (value==null||value=="")
    {alert(alerttxt);return false}
  else {return true}
  }
}

function validate_form(thisform)
{
with (thisform)
  {
  if (validate_required(email,"Email must be filled out!")==false)
    {email.focus();return false}
  }
}
</script>
</head>

<body>
<form action="submitpage.htm" onsubmit="return validate_form(this)" method="post">
Email: <input type="text" name="email" size="30">
<input type="submit" value="Submit"> 
</form>
</body>

</html>

E-mail 验证

下面的函数检查输入的数据是否符合电子邮件地址的基本语法。

意思就是说,输入的数据必须包含 @ 符号和点号(.)。同时,@ 不可以是邮件地址的首字符,并且 @ 之后需有至少一个点号:

function validate_email(field,alerttxt)
{
with (field)
{
apos=value.indexOf("@")
dotpos=value.lastIndexOf(".")
if (apos<1||dotpos-apos<2) 
  {alert(alerttxt);return false}
else {return true}
}
}

下面是连同 HTML 表单的完整代码:

<html>
<head>
<script type="text/javascript">
function validate_email(field,alerttxt)
{
with (field)
{
apos=value.indexOf("@")
dotpos=value.lastIndexOf(".")
if (apos<1||dotpos-apos<2) 
  {alert(alerttxt);return false}
else {return true}
}
}

function validate_form(thisform)
{
with (thisform)
{
if (validate_email(email,"Not a valid e-mail address!")==false)
  {email.focus();return false}
}
}
</script>
</head>

<body>
<form action="submitpage.htm"onsubmit="return validate_form(this);" method="post">
Email: <input type="text" name="email" size="30">
<input type="submit" value="Submit"> 
</form>
</body>

</html>