论坛首页 Web前端技术论坛

一个极简化的Ajax封装,回调接口和浏览器兼容性较好

浏览 9453 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-06-23  
>>注意:请下载后面(9楼)的v1.1正式版。如果要优先考虑IE7中的Native XHR,请自己把附件中bajax.js文件里的bajax_object函数替换一下(修改的代码在9楼的页面里——不想更新附件了)。

前一段时间写51ditu和动易的集成,现在准备改进成Ajax的。很早以前就知道了Ajax,但一直没有实际用过。
网上Google了一番,看了Sajax.php……

还是简单点好,自己写了个很小的封装,测试对浏览器的兼容性还不错,并且回调函数的接口比较友好。

另:经测试,发现如果是对同一个XMLHttpReques对象进行多次open、send等操作,IE会有Cache问题,Firefox正常。但如果是每一次都是重新new一个的话,IE就支持得很好了(Firefox自然不用说)。

用这个库(面向用户的其实就一个函数),不用考虑XMLHttpRequest的任何细节,就如同调用和定义普通的Js函数。

用法:
<script language="javascript" src="bajax.js"></script>
<script language="javascript">
function callback(req, id) {
    if(req.readyState == 4 && req.status == 200) {
        if(id)document.getElementById(id).innerHTML = req.responseText;
        //eval(req.responseText);
    }
}
</script>
<div id="someid"></div>
<div onClick="bajax_send('http://xxx.net/yourscript.php?xxx', callback, 'someid')">点击查看哦!</div>


附源码内容
var bajax_debug_enable = false;

// 主函数:
//(URL,回调函数,传递给回调函数的附加数据,方法,POST数据,是否异步)
function bajax_send(url, callback, fdata, method, sdata, asyn)
{
    fdata = (fdata === undefined)? null: fdata;
    method = method || "GET";
    sdata = (sdata === undefined)? null: sdata;
    asyn = (asyn === undefined)? true: asyn;

    var X = new bajax_object();
    if(asyn)
        X.onreadystatechange = function(){ callback(X, fdata); };
    X.open(method, url, asyn);

    if(bajax_debug_enable)
        bajax_debugger(callback);
    X.send(sdata);

    if(asyn) return X;
    else callback(X, fdata);
}

// 兼容IE与其它浏览器(From Sajax.php v0.12)
function bajax_object()
{
    var A;
    var _msxmlhttp = new Array(
        'Msxml2.XMLHTTP.5.0',
        'Msxml2.XMLHTTP.4.0',
        'Msxml2.XMLHTTP.3.0',
        'Msxml2.XMLHTTP',
        'Microsoft.XMLHTTP');
    for(var i = 0; i < _msxmlhttp.length; i++) {
        try {
            if(A = new ActiveXObject(_msxmlhttp[i])) break;
        } catch (e) {
            A = null;
        }
    }
    if(!A && typeof XMLHttpRequest != "undefined")
        A = new XMLHttpRequest();
    if(!A)
        alert("Could not create connection object.");

    return A;
}

// Debug information...
function bajax_debugger(func)
{
    var S = func.toString();
    alert('[Running] ' + S.slice(9, S.indexOf(')', 10)) + ')');
}
  • bajax.js.rar (1.3 KB)
  • 描述: Ajax 简易封装.修订
  • 下载次数: 279
   发表时间:2007-06-25  
呵呵,怎么没人回一哈啊。。。。

自己补充一下:

  我不太清楚IE、Firefox或是其它浏览器申请一个XMLHttpRequest对象的开销有多大?因为每个Ajax请求都是申请一个新的XMLHttpRequest对象。这样做的好处是不存在在全局域管理一个XMLHttpRequest对象池之类的东西,各请求对象之间没有冲突,程序好写。不足之处可能就是会有开销的问题(估计问题不大,毕竟OO就是在使用对象嘛,呵呵)。
  另外,能够传递一个附加的数据到回调函数中,也是一种极大的方便。比如可以传递一个外部容器的Id,或者一个需要用响应数据操作的对象、甚至可以传递一个数组,以用于与服务器响应数据的复杂操作等。

  (创建XMLHttpRequest对象的兼容代码来源于Sajax.php v0.12,在此声明一下。)
0 请登录后投票
   发表时间:2007-07-20  
快一个月了,想强化一下Ajax的封装——有“对象池管理”的功能。测试时附带验证这个Bajax的POST操作(以前只是使用GET方法)…………呵呵,大跌眼镜——因为没有设置必要的Header,POST是没有成功的!惨

毕竟只是才学啊,Http的请求模型都没得搞明白 

现在修正Bug,并且接口完全改了:把POST和GET分作2个独立的函数,直接使用更方便。

>>原始内容删除。请查看/下载后面(9楼)的正式版。
  • bajax_v0.5.rar (1.1 KB)
  • 描述: Bajax 更新版,文件已用jsmin压缩。
  • 下载次数: 61
0 请登录后投票
   发表时间:2007-07-20  
1. 应该只使用 msxml2.xmlhttp.6.0和3.0,具体原因请搜索IEBlog。
2. 虽然没有仔细看,不过你的代码很有可能会有内存泄露。。。
0 请登录后投票
   发表时间:2007-07-21  
hax 写道
1. 应该只使用 msxml2.xmlhttp.6.0和3.0,具体原因请搜索IEBlog。
2. 虽然没有仔细看,不过你的代码很有可能会有内存泄露。。。

不知内存泄漏会出现在哪里?
JS是有内存垃圾收集处理功能的。
可能的一种情况是:因为每次都是创建一个新的请求对象(xhr),返回的对象可能被无限期存储起来而没有释放(一个变量被赋值新的对象,原来的那个值是会进入垃圾处理的)。但这应该是应用的问题了。

>>1. 应该只使用 msxml2.xmlhttp.6.0和3.0,具体原因请搜索IEBlog。
bajax_object的代码是从Sajax.php中拷过来的,没仔细研究。查哈看。。
谢谢
0 请登录后投票
   发表时间:2007-07-23  
 function callback(req, id) {  
     if(req.readyState == 4 && req.status == 200) {  
         var _node = document.getElementById(id);  
         if(_node) _node.innerHTML = 'Hai ' + req.responseText;  

// clear the reference
         req.onreadystatechange = null;

     }  
 }  


注意我加的那句,没有这句,在IE6下会有内存泄漏。
0 请登录后投票
   发表时间:2007-07-23  
BTW,实际上面还不是最严谨,因为出错的时候也应该置为null。
0 请登录后投票
   发表时间:2007-07-23  
不了解 MS 的 ActiveXObject,看来真是有些特别
得改一下回调函数的格式约定了,呵呵
function callback(req, id)
{
    if(req.readyState == 4) {
        if(req.status != 200) {
            // do some thing.
            req.onreadystatechange = null;
        }else{
            var _node = document.getElementById(id);
            if(_node) _node.innerHTML = 'Hai ' + req.responseText;

            // clear the reference
            req.onreadystatechange = null;
        }
    }
}

谢谢hax给予如此详细的指正。
0 请登录后投票
   发表时间:2007-07-23  
唉。。。。干脆彻底改一下,用OO封装得了。(谢谢hax提供的修补)
以下为Bajax的正式版,呵呵  。用法与前面稍有不同。

用法:
<script language="javascript" src="bajax.js"></script>
<script language="javascript">
function callback(req, id) {
    var _node = document.getElementById(id);
    // 直接使用req的响应值
    if(_node) _node.innerHTML = 'Hai ' + req.responseText;
}
var _obj = new Bajax();
</script>
<div id="someid"></div>
<div onClick="_obj.get('/script.php?name=Liner', callback, 'someid')">GET方法</div>
<div onClick="_obj.post('/script.php', 'name=Liner', callback, 'someid')">POST方法</div>

源代码:
/** bajax.js
 *  Base Ajax 简易封装 2007.07.20
 *  ---------------------------------------------------------------------------
 *  >>接口:
 *      get, post	常用普通接口。
 *      e_handler	出错处理句柄,可选。
 *      _object		创建浏览器兼容XHR的包装。
 *
 *  >>参数:
 *      @url:		请求的响应页面;
 *      @sdata:		POST的数据;
 *      @callback:	处理响应数据的回调函数;
 *
 *  以下参数可选
 *      @fdata:		传递给回调函数的数据,默认null;
 *      @asyn:		是否异步,默认true。
 *
 *  返回值:
 *      如果是异步,返回异步请求对象;否则不返回。
 *
 *  >>回调函数:
 *
 *      回调函数有两个参数:(req, data)
 *      @req:		异步请求对象(XMLHttpRequest 或 ActiveXObject)
 *      @data:		传入的附加数据。
 *
 *  >>注意:
 *
 *      1、传递到回调函数的附加数据可以是数值、字串、数组或对象。
 *      2、可置e_handler的参数为null来取消出错处理。
 *
 *  @Author: Tubz.
 *  @Copyright: GNU - LGPL.
 *  ---------------------------------------------------------------------------
 */

function Bajax()
{
    // 默认出错处理
    this._eh = Bajax._error;
}

// 调试设置
Bajax.debug_enable = false;

//-- 用户接口 -----------------------------------------------------------------

// GET 请求
//(URL, 回调函数[, 回调函数附加数据, 是否异步])
Bajax.prototype.get = function (url, callback, fdata, asyn)
{
    fdata = (fdata === undefined)? null: fdata;
    asyn = (asyn === undefined)? true: asyn;
    var _self = this;

    var X = Bajax._object();
    if(asyn)
        X.onreadystatechange = function()
        { Bajax._callback(X, callback, fdata, _self); };
    X.open('GET', url, asyn);

    if(Bajax.debug_enable)
        Bajax._debugger(callback);

    X.send(null);

    if(asyn){
        return X;
    }else{
        Bajax._callback(X, callback, fdata, _self);
    }
}

// POST 请求
//(URL, POST数据, 回调函数[, 回调函数附加数据, 是否异步])
Bajax.prototype.post = function (url, sdata, callback, fdata, asyn)
{
    fdata = (fdata === undefined)? null: fdata;
    asyn = (asyn === undefined)? true: asyn;
    var _self = this;

    var X = Bajax._object();
    if(asyn)
        X.onreadystatechange = function()
        { Bajax._callback(X, callback, fdata, _self); };
    X.open('POST', url, asyn);

    if(Bajax.debug_enable)
        Bajax._debugger(callback);

    X.setRequestHeader('Content-length', sdata.length);
    X.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');

    X.send(sdata);

    if(asyn){
        return X;
    }else{
        Bajax._callback(X, callback, fdata, _self);
    }
}

// 设置出错处理函数
Bajax.prototype.e_handler = function (func)
{
    if(func !== undefined) this._eh = func;
}

// 创建一个兼容的XHR对象。
// 改了一下:IE7中优先采用Native XHR
Bajax._object = function()
{
    var A;
    if(typeof XMLHttpRequest != 'undefined') {
        A = new XMLHttpRequest();
    }else{
        var _msxmlhttp = new Array(
            'Msxml2.XMLHTTP.6.0',
            'Msxml2.XMLHTTP.3.0',
            'Msxml2.XMLHTTP',
            'Microsoft.XMLHTTP');
        for(var i = 0; i < _msxmlhttp.length; i++) {
            try {
                if(A = new ActiveXObject(_msxmlhttp[i])) break;
            } catch (e) {
                A = null;
            }
        }
    }
    if(!A)
        alert("Could not create connection object.");
    return A;
}

//-- 私有函数 -----------------------------------------------------------------

Bajax._callback = function (req, callback, data, obj)
{
    if(req.readyState == 4) {
        if(req.status != 200) {
            //req.onreadystatechange = null;
            if(obj._eh) obj._eh(req, callback);
        }else{
            callback(req, data);
            //req.onreadystatechange = null;
        }
    }
}

// Debug: 显示采用的回调函数。
Bajax._debugger = function (func)
{
    alert('running: ' + Bajax._fname(func));
}

// 默认的出错处理
Bajax._error = function (req, callback)
{
    alert(req.statusText + '\nShould run: ' + Bajax._fname(callback));
}

// 提取函数名(含参数)
Bajax._fname = function (func)
{
    var S = func.toString();
    return S.slice(9, S.indexOf(')', 10)) + ')';
}
//-- End.----------------------------------------------------------------------

  注:v1.0版在IE中可能会有些问题,同时异步时出错抛出的异常难以处理。请用v1.1。
  • bajax_v1.0.rar (2.7 KB)
  • 描述: Bajax正式版1.0,采用面向对象的封装。
  • 下载次数: 51
  • bajax_v1.1.rar (2.9 KB)
  • 描述: Bajax1.1,改进了出错处理方式,可自行设置错误处理函数。
  • 下载次数: 229
1 请登录后投票
   发表时间:2007-07-24  
不好意思,请教hax:
按照你的说法:req.onreadystatechange = null;
但是这行代码在IE6中会出现运行时错误提示(Firefox中正常),何解?
这样的代码应该不是纸上谈兵吧。谢了。
0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics