随着Ajax 编程的出现,Web 应用程序在运行期间动态加载数据和功能成为常见的情形。JavaScript
和服务器之间的通信也会出现错误。
第一种错误是URL 格式或发送数据的格式不正确。通常,在把数据发送到服务器之前没有用encodeURIComponent()编码,会导致这种错误。例如,下面的URL 格式就不正确:
http://www.yourdomain.com/?redir=http://www.someotherdomain.com?a=b&c=d
这个URL 可以通过用encodeURIComponent()编码"redir=“后面的内容来修复,得到的结果如
下所示:å
http://www.example.com/?redir=http%3A%2F%2Fwww.someotherdomain.com%3Fa%3Db%26c%3Dd
对于查询字符串,应该都要通过encodeURIComponent()编码。为此,可以专门定义一个处理查
询字符串的函数,比如:
function addQueryStringArg(url, name, value) {
if (url.indexOf(”?") == -1){
url += “?”;
} else {
url += “&”;
}
url += ‘KaTeX parse error: Expected '}', got 'EOF' at end of input: …omponent(name)={encodeURIComponent(value)}’;
return url;
}
这个函数接收三个参数:要添加查询字符串的URL、参数名和参数值。如果URL 不包含问号,则
要给它加上一个;否则就要使用和号(&),以便拼接更多参数和值,因为这意味着前面已有其他查询参
数了。查询字符串的名和值在被编码之后会被添加到URL 中。可以像下面这样使用这个函数:
const url = “http://www.somedomain.com”;
const newUrl = addQueryStringArg(url, “redir”,
“http://www.someotherdomain.com?a=b&c=d”);
console.log(newUrl);
使用这个函数而不是手动构建URL 可以保证编码合适,以避免相关错误发生。
在服务器响应非预期值时也会发生通信错误。在动态加载脚本或样式时,请求的资源有可能不可用。
有些浏览器在没有返回预期资源时会静默失败,而其他浏览器则会报告错误。不过,在动态加载资源的
情况下出错,是不太好做错误处理的。有时候,使用Ajax 通信可能会提供关于错误条件的更多信息。
区分重大与非重大错误
任何错误处理策略中一个非常重要的方面就是确定某个错误是否为重大错误。具有以下一个或多个
特性的错误属于非重大错误:
不会影响用户的主要任务;
只会影响页面中某个部分;
可以恢复;
重复操作可能成功。
本质上,不需要担心非重大错误。例如,Gmail 有一个功能,可以让用户在其界面上发送环聊
(Hangouts)消息。如果在某个条件下,环聊功能不工作了,就不能算重大错误,因为这不是应用程序
的主要功能。Gmail 主要用于阅读和撰写电子邮件,只要用户可以做到这一点,就没有理由中断用户体
验。对于非重大错误,无须明确给用户发送消息。可以将受影响的页面区域替换成一条消息,表示该功
能暂时不能使用,但不需要中断用户体验。
另一方面,重大错误具备如下特性:
应用程序绝对无法继续运行;
错误严重影响了用户的主要目标;
会导致其他错误发生。
理解JavaScript 中何时会发生重大错误极其重要,因为这样才能采取应对措施。当重大错误发生时,
应该立即发送消息让用户知晓自己不能再继续使用应用程序了。如果必须刷新页面才能恢复应用程序,
那就应该明确告知用户,并提供一个自动刷新页面的按钮。
代码中则不要区分什么是或什么不是重大错误。非重大错误和重大错误的区别主要体现在对用户的
影响上。好的代码设计意味着应用程序某个部分的错误不会影响其他部分,实际上根本不应该相关。例
如,在个性化的主页上,比如Gmail,可能包含多个相互独立的功能模块。如果每个模块都通过JavaScript
调用来初始化,那就可能会在代码中看到以下逻辑:
for (let mod of mods){
mod.init(); // 可能的重大错误
}
表面上看,这段代码没什么问题,就是依次调用每个模块的init()方法。问题在于,这里只要有
一个模块的init()方法出错,数组中其后的所有模块都不会被初始化。如果错误发生在第一个模块上,
页面上就没有模块会被初始化了。逻辑上,这样写代码是不合适的,因为每个模块相互独立,各自功能
没有相关性。由此可能导致重大错误的原因是代码的结构。好在可以简单地重写以上代码,让每个模块
的错误变成非重大错误:
for (let mod of mods){
try {
mod.init();
} catch (ex){
// 在这里处理错误
}
}
通过在for 循环中加入try/catch 语句,模块初始化过程中的任何错误都不会影响其他模块初始
化。如果代码中有错误发生,则可以单独处理,并不会影响用户体验。
javascript七基础学习系列一千九百二十五:通信错误
最新推荐文章于 2024-08-27 13:38:21 发布