一次Ajax查错的经历

一次Ajax查错的经历

先说故事,再说想法吧。

我有一朋友做网站,用jQuery的Ajax方法从后端载入一段HTML代码然后动态插入到网页的Div元件中。这个东西太普遍了。jQuery强大的load方法可以完成这个事情。朋友的代码是这么写的:

[javascript]var tab = jQuery("#dynamic_tab");
var url = "/list_ajax/";
tab.load(url);[/javascript]

简单到不能再简单了。在Chrome,Firefox,Safari下运行一点问题也没有,只有IE不行,不管是IE7,IE8,还是IE9。问题的症壮是,使用IE访问那个Ajax的链接,没有问题,但是在jQuery的Ajax方法返回了“undefined”的respons对象。没有任何报错!

怎么搞也搞不定,只好Google了一下——“jQuery load IE”,一看,很多人都在问这个问题。于是开始了散弹枪编程方式

排在第一的就是StackOverflow被浏览了33K次的这个问题:jQuery’s .load() not working in IE – but fine in Firefox, Chrome and Safari,答案没有被打勾(不靠谱),StackOverflow还有很多人问相似的问题,不过都没有答案。不管三七二十一,先试了一下,散弹枪嘛。试了半天都没有用。

然后上Google查,又看到有人说的IE缓存的问题,什么,要把cache设置成false,或是用下面的方法来解决:

[javascript]var tab = jQuery("#dynamic_tab");
var fuckie = Math.random();
var url = "/list_ajax/"+"?fuckie="+fuckie;
tab.load(url);[/javascript]

反正还是一样,统统不Work,几乎所有的都试了,都不Work。搞了一天的朋友恼怒道:“Microsoft应该快点倒闭吧,产品太烂了”。IE的确是太烂了。

于是我用IE9的网页调试器可以看到点了Ajax的链接后,IE对网站有http的Ajax请求,也可以看到请求返回了,但是就是不显示在我的页面上——jQuery的Ajax的responseText为undefined!

对于我这个老家伙,对jQuery也不熟,我只得开始调试jQuery的代码,想看看里面干了什么,报了什么错?调了一个小时,基本上把jQuery的Ajax的封装看懂了七七八八了,但是还是没找到为什么有问题。

于是,我只得架起原生态的Ajax,看看IE的那个Ajax的ActiveX的对象干了什么事?写了下面的代码(当年写Ajax就是这么写的,所以也不费劲,况且网上还有例程可以抄):

[javascript]
function InitAjax()
{
var ajax=false;
try {
ajax = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
ajax = new ActiveXObject("Microsoft.XMLHTTP");
} catch (E) {
ajax = false;
}
}
if (!ajax && typeof XMLHttpRequest!=’undefined’) {
ajax = new XMLHttpRequest();
}
return ajax;
}

var ajax = InitAjax();
ajax.open("GET", url, true);
ajax.onreadystatechange = function() {
if (ajax.readyState == 4 && ajax.status == 200) {
var show = document.getElementById("HaoChenDIV").value;
show.innerHTML = ajax.responseText;
}
}
ajax.send(null);
[/javascript]

一运行,还是不行,没见IE报什么错,不过,可以确定这不是jQuery的问题了,估计还是我们自己程序的问题。不过此时的程序太好调试了,调试中,在IE9下调式发现原生的IE的Ajax对象在onreadystatechange函数里,其responseText是下面这个样子:

什么是“系统错误: -1072896658”?上google一查,一堆页面,基本上是说乱码了,也就是ajax的后端程序返回的网页编码不认识吧。需要在返回的http header里加上 charset=utf-8。

于是,修改后端的Ajax的程序,明确指定了返回的HTTP Header中的charset,于是IE下就工作正常了,再切回jQuery的load代码,一切正常了(后端的程序本来是utf-8的编码格式,但是不骨明确在HTTP Header中指定,但是只有IE不会自动检测)。

这个问题的原因就是因为我们没有按照规范去写网页。所以,举一反三,HTML的规范还有哪些,太多了,记也记不住。但也许你会知道有一个叫 http://validator.w3.org 的网站可以帮你校验你网页中的很多不规范的东西。这个工具会报很多很多错,很多都有点吹毛求疵,不过,可以让你看看(注:今天的coolshell装了很多插件,也被我调过一些东西,所以出错很多,我还记得以前没有插件没有我定制化的样式的时候,Wordpress一个错都不报)。

后记

我把这个问题和过程分享出来,主要有这么几个目的,并抛出几个问题,大家可以思考一下:

1)这个问题网上有很多人都在报,但是基本上找不到答案(包括StackOverflow),所以,我分享出来,填补一下空白。

2)我相信我们的程序员天天都在经历这样的事,我不知道大家在遇到这样的事情会怎么做?也许大多数人都在网上查各种解决方案,然后一个一个的试,直到试对了——散弹枪式的编程,呵呵。当然,大多数答案都是可能找到的。但当我们找到答案了后,我们还会深入去了解这个问题的具体原因并举一反三地去思考一其周边的东西吗

3)另外,在今天这样N多框架,N多lib,N多开源的年代下,不知道大家有没有失去了从零开始自己写代码的能力?比如上面的这个问题,不知道有多少人还会自己写原生态的Ajax?不过,我还是建议大家能在使用各种框架的时候,明白那些最基础的知识,求甚解,知其然知其所以然,真的很重要。

我是从那个“吃糠的年代”过来的程序员,那时的程序员什么都要自己干,很辛苦,今天我和很多人说我以前的那些经历,会被笑话,但是我从这些什么都自己的干的年代过的经历,让我受益很多。我把我的想法分享给大家,希望对大家有用。

(全文完)

(转载本站文章请注明作者和出处 酷 壳 – CoolShell ,请勿用于任何商业用途)

好烂啊有点差凑合看看还不错很精彩 (35 人打了分,平均分: 3.86 )
Loading...

一次Ajax查错的经历》的相关评论

  1. 还有一个很大的问题其实就是fire and forget,且jQuery没有在错误的时候提示用户。假如加一个error handler或者jQuery打印出个warning或是error,哪会卡这么长时间。当然还有一个可能就是程序员没有看warning或是error。

    总之这个问题也可以牵涉到API设计还有编程习惯等等……

  2. 类似的我也碰到过,不过我是从前端往后端传递信息。比如说ajax传递汉字,其他浏览器都正常就IE下不能正常工作,只能encode下,要不然IE传递到后端的就乱码。后来无意中发现改用Post传递就一切正常,也不用encode了,不知道这是为什么

  3. 这个问题我也碰到过,自己也解决了,但遗憾的是没有举一反三思考其周边的若干问题。我到现在有时候还在用原生态的ajax,包括其他javascript 功能。

  4. 您好!我也是来看想法的,不过我也吹毛求疵一点。文中是“问题的症壮”有别字,还有一个“不骨明确”也有点问题吧。

    1. jQuery的不是responseText,而是response,responseText是IE的Ajax对象的东西,所以基本不会用responseText去搜的。搜不到jQuery的那个,另,stackoverflow的那个回答太含糊了。

  5. 霰弹枪式编程的精髓在于, 不是分析问题所在然后对症下药, 而是瞎猜.

    我觉得用搜索引擎寻找答案并不是霰弹枪式编程, 我的上一个回复例证了关键字选取得当的情况下搜索引擎给出的答案是相当精确的, 这是充分利用了现代工具的对症下药. 正如你所说, HTML/JS规范这种东西, 没人会整个背下来然后闷头瞎写, 重要的是了解精髓, 然后需要什么东西要知道在哪儿查, 如何查, 这就足够了.

    另外我觉得最后一段有点倚老卖老的意思, 我入门的时候已经流行BASIC, 现在主要使用Python, 之前工作的关系C功底还不错, 另外因为兴趣学了点x86汇编, 有那些基础能帮我更好的理解很多东西, 这并不是因为我老, 也并不是因为”什么都自己干”而被迫的.

    “今天我和很多人说我以前的那些经历,会被笑话”, 我觉得这种人就不用理了.

  6. 之前遇到过,导出excel文件名中文乱码问题,也是调了一下午,网上也查了很多,都不行。最后用encode搞定,乱码问题才是最烦人的

  7. 这个Bug倒是没有遇到过,因为不习惯直接用load这种过于傻瓜的方法。load方法有很多弊端、比如你不能对返回的数据的有效性做检查,正常的页面是HTML,重定向到的登录页面、404页面也是HTML,如何区分?我更习惯只让后台返回数据,包括状态码来区分是否成功返回,以及用来渲染的数据,前端自己渲染。这样灵活度更高一些。否则直接用load肯定一旦遇到编码、错误的标签嵌套什么的都会出现问题。IE的innerHTML方法有个很奇怪的特性,会对里边的内容做语法检查一旦遇到错误的标签嵌套比如:p1p2会报一个错误:未指明的错误。

  8. 这篇文章跟我写的那段代码,症状真的是一个样,我也是在后端用php写的html,只是应用的ajax分页,ajax作为内层分页,外层还有一个分页,然后我用的是eval来执行一段js代码,然后请求会递归的执行eval,其它浏览器可以,就是IE不行,那个纠结,结果也懒得调试,由于界面的重新设计。

  9. jquery 的load 方法还有一个问题: 如果返回的html文件开头部分有太多的空行, IE可能不会显示这段html

    前面空行太多的原因:多层次的在jsp中引用jsp,而每个jsp页面的头几行 的@page @include都是必须的,虽然这些标签本身不输出任何东西,但它本身所占的那一行的回车换行符都会被输出到浏览器,经过多层引用后,多个@page @include 所占的空行相加,当空行过多就会出现这个问题。

    最后我没用load, 用了ajax方法并用trim去掉了开头过多的空格, 再用了html()方法,才正常

  10. 虽然我现在没做网页,但是这段代码应该有问题吧:
    var show = document.getElementById(“HaoChenDIV”).value;
    show.innerHTML = ajax.responseText;
    既然show是DIV的value属性,它有innerHTML属性么?

  11. 语言编码、字符集的原因,可能老外遇到的比较少,没特别注意。
    这些“晕”也是我讨厌js、b/s的原因之一:不靠谱。。。。。

  12. 如果IE没法用,就不用支持IE,在打开网页的时候弹个对话框,给个chrome,firefox,或者safari的链接,让用户用这些支持的浏览器就行了。

  13. jQuery的AJAX中默认都是使用utf-8编码,所以如果你的web应用或者网站使用gbk或者gb2312等编码,使用jQuery的ajax方法会遇到很多类似的问题,workaround就是使用内部转码机制,所以为了更好的使用jquery,你的构建上需要使用utf-8,其实在jquery的官方文档里已经说明了,只不过不是很明显。

  14. Destiny :
    虽然我现在没做网页,但是这段代码应该有问题吧:
    var show = document.getElementById(“HaoChenDIV”).value;
    show.innerHTML = ajax.responseText;
    既然show是DIV的value属性,它有innerHTML属性么?

    博主写错了吧!

  15. 如果问题出现第一遍的时候,先二分法确认下是客户端浏览器的问题,还是服务端处理的问题,应该可以快速定位。
    结合httpwatch或者firebug工具跟踪下http请求记录。

    如果已经到了服务器,那根据http请求记录的响应内容,可以判断编码问题还是其他问题;
    如果没到服务,铁定了是jQuery内部的bug或者自身bug的问题了。

    总体上来看,web的问题排查,关键的是确认好3个点;客户端、传输过程、服务器端。
    一旦范围界定了,问题排查也快多了。

  16. 其实用jq的ajax方法就可以把错误揪出来。请求返回200状态以后,并不会马上回调success方法,而是先回调complete方法,根据指定的dataType把返回回来的数据正确解析以后,才会回调success方法。举个例子(jee的例子):如果后台response指定了MIME类型为xml,而前台的jq的ajax方法指定了json格式,那么http返回200后,只能到达complete,而到不了success,complete方法里面可以查看到responseText.
    ajax请求里头的小道道还是有不少的(详见jq的ajax方法参数配置),只有真正掌握了XHR异步请求对象,才算掌握jq的ajax请求。

  17. 我现在遇到一个问题:
    我输出的html有两部分组成:前半部分是数据,javascript代码,编码是gbk,但是后面整个页面是utf-8的编码,也就是整个页面要以utf-8的格式显示,现在就遇到了问题,前面gbk编码的中文显示乱码,找了很久都没有找到解决办法。当然可以把前面输出的数据改成utf-8就可以了,但是这样对我目前而言是下策,所以,想请教一下有没有办法能直接把gbk编码的字符串在utf8的页面中显示。

  18. 要精通一个框架,最好的方法就是自己去实现一个。现在大多数程序员只会用框架,碰到问题就只能上霰弹枪了。

  19. 以前折腾原生ajax的时候折腾过, 现在基本都会下意识的去先检查http请求, 纵使不确定是不是哪个原因, 但是按照严谨的做法来, 可以天然避免掉不必要的时间浪费

  20. ajax服务器返回的gb2312的编码方式,ajax默认的编码是utf-8,所以乱码,你强制将返回的http消息封装成utf-8问题解决了(其实这也和浏览器有关系,ie啊ie),感悟是,不论任何的js框架在和服务器和客户端打交道时只要弄清了,这个框架怎么按什么编码方式发送数据,接受数据,服务器端是如何响应的额,以及发送的,那么乱码问题就不存在。陈老师在这个地方显而是一点点式才搞出来的。(估计你也按以前的做过这个的方法试吧,呵呵)有时候经验确实是王道,但是有时候会陷入怪圈,个人觉得明白了原理,烂熟于心才是王道,经验是知道我们再次做同样的事情不会犯错,但是稍微有点创新或者环境不一样了,经验就不适用了!@陈皓 你觉得呢陈皓 老师。还有看上面有些前辈讲,get提交要encode,post提交正常,这是由于get提交和post提交的编码方式不一样,你可以google下@金针菇

回复 ccppjava 取消回复

您的电子邮箱地址不会被公开。 必填项已用*标注