用javascript监听页面上的所有ajax请求我们自己是个Grails,集成了另外一个web程序,我们把那个web程序放在
用javascript监听页面上的所有ajax请求
我们自己是个Grails,集成了另外一个web程序,我们把那个web程序放在我们提供的iframe里。那个web程序只有在第一次初始化的时候是一个普通的HTTP请求,之后在页面上的操作,都是通过ajax来操作的。现在我们有个需求,我们需要知道iframe里面做了什么操作。
没法改别人的代码,那我们只能监测里面的事件了,所以总归来说,要找到一种方法来检测到iframe里面的所有ajax请求。
Javascript框架熟悉的就只有JQuery,所以第一个想到的是用JQuery,看看有没有提供什么方法。找到了,JQuery确实提供了监听ajax的工具方法,如:
?
[javascript]?view plaincopy
- $("#msg").ajaxComplete(function(event,request,?settings){??
- ???$(this).append("<li>请求完成.</li>");??
- ?});??
这个方法会在所有ajax请求完成后被调用。
?
再深入找资料,想知道这个方法的原理,发现,原来JQuery提供的监听ajax的方法,只对本身就是用JQuery发出去的请求才有效。原理上也就简单了,在JQuery自己的代码里插入一些控制就实现了。
继续查资料,终于在stackoverflow找到了答案:用来发送ajax的对象XMLHttpRequest本身自己就是一个javascript对象(IE6除外),javascript对象就一定有prototype属性,有这个属性,那我就可以改这个属性的内容。
prototype属性是什么东西,我们这里没法详细描述,简单描述一下就是:我们可以用这个熟悉来修改对象,给对象添加/修改属性或者方法
接下来就和javascript实现继承一样了,我们要做的就是合理的修改XMLHttpRequest的open,send子类的方法,嵌入我们自己的callback代码,即可实现对所有ajax请求的监听。?
封装stackoverflow上的代码,写了一个工具类,代码如下:
?
[javascript]?view plaincopy
- function?ajaxSend(objectOfXMLHttpRequest,?callback)?{??
- ????//?http://stackoverflow.com/questions/3596583/javascript-detect-an-ajax-event??
- ????if(!callback){??
- ????????return;??
- ????}??
- ??????
- ????var?s_ajaxListener?=?new?Object();??
- ????s_ajaxListener.tempOpen?=?objectOfXMLHttpRequest.prototype.open;??
- ????s_ajaxListener.tempSend?=?objectOfXMLHttpRequest.prototype.send;??
- ????s_ajaxListener.callback?=?function?()?{??
- ????????//?this.method?:the?ajax?method?used??
- ????????//?this.url?:the?url?of?the?requested?script?(including?query?string,?if?any)?(urlencoded)??
- ????????//?this.data?:the?data?sent,?if?any?ex:?foo=bar&a=b?(urlencoded)??
- ????????callback(this.method,?this.url,?this.data);??
- ????}??
- ??????
- ????objectOfXMLHttpRequest.prototype.open?=?function(a,b)?{??
- ????????if?(!a)?var?a='';??
- ????????if?(!b)?var?b='';??
- ????????s_ajaxListener.tempOpen.apply(this,?arguments);??
- ????????s_ajaxListener.method?=?a;????
- ????????s_ajaxListener.url?=?b;??
- ????????if?(a.toLowerCase()?==?'get')?{??
- ????????????s_ajaxListener.data?=?b.split('?');??
- ????????????s_ajaxListener.data?=?s_ajaxListener.data[1];??
- ????????}??
- ????}??
- ??????
- ????objectOfXMLHttpRequest.prototype.send?=?function(a,b)?{??
- ????????if?(!a)?var?a='';??
- ????????if?(!b)?var?b='';??
- ????????s_ajaxListener.tempSend.apply(this,?arguments);??
- ????????if(s_ajaxListener.method.toLowerCase()?==?'post')?{??
- ????????????s_ajaxListener.data?=?a;??
- ????????}??
- ????????s_ajaxListener.callback();??
- ????}??
- }??
这个工具方法输入两个参数:
?
第一个参数是要监听的页面里的XMLHttpRequest对象
第二个参数是一个回调function,回调funtion接收三个参数,分别是
? ? ? ? method :ajax请求的方法,Get,Post,Put之类
? ? ? ? url :请求的URL
? ? ? ? data :请求的数据
看回工具方法的实现,实现原理就是也简单:
第一步:把XMLHttpRequest自身的open,send方法保存起来,存在临时变量里
第二步:修改open方法,新的open方法先调用第一步存起来的XMLHttpRequest自身的open方法,然后把请求时的参数保存到一些变量里以备后面用
第三步:修改send方法,新的send方法先调用第一步存起来的XMLHttpRequest自身的send方法,然后调用callback方法,callback的参数就是在第二步存起来的那些open时候的参数
最后,对于我们自己来说,就是把上面的代码加到iframe上了,
第一步:写一个callback,类似这样:
?
[javascript]?view plaincopy
- function?onAjaxSend(method,?url,?data)?{??
- }??
第二步:设置iframe的onload属性为onload="ajaxSend(this.contentWindow.XMLHttpRequest, onAjaxSend);"
?
完工,不足的地方是不支持IE6,好在我们本身就不要对IE6提供支持,也就这样过了