`
Liner
  • 浏览: 138843 次
  • 性别: Icon_minigender_1
  • 来自: 西南边陲
社区版块
存档分类
最新评论

具有xhr对象管理功能的Ajax简易封装(Majax)

阅读更多
内部由一个数组缓存工作中的xhr对象,类似于“池”,当一个请求发生时,由池中首个空闲的xhr对象执行相关操作,当请求处理完毕后,对象被回收。

这在网络速度无法保证、服务器端响应较慢,而Ajax采用异步方式时很有用。外部可以把一个Majax实例当作具有自动缓冲机制并持久有效的异步通讯对象看待。

使用接口简单并且灵活,回调函数接口也十分友好。详细内容可参看源码中的注释,希望大家喜欢。

用法:
<script language="javascript" src="majax.js"></script>
<script language="javascript">
function callback(req, id) {
    // 直接使用
    document.getElementById(id).innerHTML = req.responseText;
}
var _mObj = new Majax();
</script>
<div id="someid"></div>
<div onClick="_mObj.get('/yourscript.php?name=xxx', callback, 'someid')">GET方式</div>
<div onClick="_mObj.post('/yourscript.php', 'name=xxx', callback, 'someid')">POST方式</div>


提示:回调函数中的第二个参数可以传递任意类型的数据,所以可以在异步设计的时候用于协调一些状态。使用中如果发现Bug,欢迎在此留言或Email:tubz@21cn.com

接口示例(假如已 var _mObj = new Majax();):
//-- 普通接口 -----------------------------------------------------------------

// GET方式请求。
// (URL, 回调函数, 传递给回调函数的附加数据, 是否异步)
_mObj.get(url, callback, fd, asyn)

// POST方式请求,Post-data仅为文本。
// (URL, POST数据, 回调函数, 传递给回调函数的附加数据, 是否异步)
_mObj.post(url, data, callback, fd, asyn)

//-- 低阶接口 -----------------------------------------------------------------

// 复位/设置请求。
// (URL, [GET|POST]方法, 是否异步)
_mObj.reset(url, method, asyn)

// 设置请求头信息。
_mObj.header(name, value)

// 发送请求(若reset时为GET,data为null)。
// (发送数据, 回调函数, 传递给回调函数的附加数据)
_mObj.send(data, callback, fd)

// 设置出错处理函数
// func(req, callback)
_mObj.e_handler(func)


压缩包内文件说明:
  majax.js 用jsmin压缩过的纯代码,实际引用文件;
  majax_.js 书写时的源代码,含注释;
  test.html/servdt.php 测试用文件。
  • majax_v0.1.rar (3.5 KB)
  • 描述: 带请求对象池管理功能的Ajax封装,接口兼顾灵活与简便。
  • 下载次数: 46
  • majax_v0.2.rar (4.2 KB)
  • 描述: 增加了出错处理接口,修复出错时xhr对象无法回收的问题。
  • 下载次数: 107
分享到:
评论
7 楼 Liner 2007-07-28  
引用

所谓忠言逆耳,既然你不想听,那我也打住。

首先谢谢你的回复,讲解得很详细。(真心感谢,我很菜,所以希望能得到明白人的指点,最好是有代码说明)
我那个到此打住的意思希望不要被顶上去,影响别的好贴被下沉。
引用

6.关于泄漏,把我的揶揄之词当成你的理由,真令人哭笑不得。

因为在论坛上我不揶揄别人(除非是老朋友),所以没看出来。
引用

>>1、请勿在回调函数和错误处理函数中抛出异常。
这点约束是非常不明智的。

是的,如果要通用就该改一下。
我本来的想法是希望用户在回调函数或错误处理中就解决掉内层抛出的异常,不再往外发(设计上的强制,但未必可行)。

其实还有一个不足,就是异步时返回的xhr对象不能被滥用。这个引用对象在对应请求的回调函数执行完之后会被回收,所以再在其上操作其实是针对另一个请求的——除非那就是想要的,否则就错了。
我本来是不想提供返回,但为灵活性还是返回了。

………………………………………………………………………………………………………………………………………

如果需要取消上面“勿在回调函数和错误处理函数中抛出异常”的限制,可以用下面的代码替换压缩包中对应的函数。
Majax._callback = function(callback, data, its, obj)
{
    var _req = its[0];

    if(_req.readyState == 4) {
        try {
            if(_req.status != 200) {
                if(obj._eh) obj._eh(its[0], callback);
            }else{
                callback(_req, data);
            }
        } finally {
            its[1] = false;
        }
    }
}

不知道该如何捕获xhr异步调用回调函数时从回调函数中抛出的异常?我觉得不应该在这里捕获,应该放行异常继续向上,或许由浏览器显示那些“难看”的代码,呵呵。
6 楼 jindw 2007-07-28  
引用

>> 补充:

1、请勿在回调函数和错误处理函数中抛出异常。


这点约束是非常不明智的。
5 楼 hax 2007-07-28  
Liner 写道
新创建一个xhr对象的开销有多大我不清楚,但是在实际应用中必须顾及浏览器的兼容性,所以创建一个xhr对象其实是需要一些代码的,比如:

但是,如果创建的对象被保留下来,在可以安全使用的前提下,返回一个现成的对象肯定要比新创建一个兼容对象快不少。对于池的复杂性,封装就是为了掩盖复杂性的,用户只需要面对接口。(白:其实代码并不复杂)

在一个页面存在大量Ajax请求的应用里,从消耗累加的角度看,用这个封装明显比每次都创建一个新的xhr要高效和节约。并且由于重复使用xhr对象,还可缓解hax所说的IE6存在的内存泄漏问题。

比较简单的东西……到此打住。


1. 既然多大开销你不清楚,那就没有充分理由用池。因为你的池可能开销更大。
2. 创建一个xhr的兼容代码不需要那么复杂。对于支持native xhr的(ff,opera,safari,ie7),根本不需要任何额外代码;对于IE6及以前的,只需要初始的时候创建一个XMLHttpRequest函数,且该函数根本不用每次都循环try catch(这是一个基本的js编程,留给大家当作业吧)。
3. 不管你掩盖的如何,如果你掩盖的复杂性本身就是没有必要的,那就应该以剃刀原则去除之。
4. 前面还说你不知道开销多少,后面又说高效节约,不知道才过了两段文字,就哪里明显了?
5. 请你好好再读读我前面的帖子,看看我为什么说js对象池没有必要,以及就算要实现池你也没实现到位。
6. 关于泄漏,把我的揶揄之词当成你的理由,真令人哭笑不得。

所谓忠言逆耳,既然你不想听,那我也打住。
4 楼 Liner 2007-07-28  
新创建一个xhr对象的开销有多大我不清楚,但是在实际应用中必须顾及浏览器的兼容性,所以创建一个xhr对象其实是需要一些代码的,比如:
function new_object()
{
    var A;
    var _msxmlhttp = new Array(
        'Msxml2.XMLHTTP.6.0',
        //'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;
}


但是,如果创建的对象被保留下来,在可以安全使用的前提下,返回一个现成的对象肯定要比新创建一个兼容对象快不少。对于池的复杂性,封装就是为了掩盖复杂性的,用户只需要面对接口。(白:其实代码并不复杂)

在一个页面存在大量Ajax请求的应用里,从消耗累加的角度看,用这个封装明显比每次都创建一个新的xhr要高效和节约。并且由于重复使用xhr对象,还可缓解hax所说的IE6存在的内存泄漏问题。

比较简单的东西……到此打住。
3 楼 hax 2007-07-23  
池增加了代码复杂度,反而可能降低效率。我估计,native的new XMLHttpRequest肯定应比你的池要高效。只有IE6,因为是创建一个AcitveX对象,可能较为低效。但是这种效率提高到底有多少?非常值得怀疑。

事实上,对象池技术在多数场合并无必要,例如在java中,只有重量级资源对象,或者反复创建相同的对象并可能影响性能,才会使用对象池。

而在js里面:
1. js对象只是XHR的wrapper,纯粹new一个js对象的开销不会比你复杂的池要大,只会小。
2. XHR自己可能存在优化。实际上,UA自己或者更底层的网络协议层,对于http请求都是有队列的。所以不用你画蛇添足。
3. 就算要用池,浏览器同源请求在同一时刻只能有2个,不同源的也有一定上限(通常10个以下),所以你真的要做池的话,其实应该控制上限。

总之,XHR的池是毫无意义的——除非你有数据证明它确实提高了效率。

BTW,使用你这个代码的“好处”是,虽然你的这个代码在IE6上会有内存泄漏,但同样是泄漏,因为你重复利用了XHR对象,所以估计你的泄漏量会小。
2 楼 Liner 2007-07-23  
确实,我不清楚xhr对象在每个浏览器实现中的开销,但是如果池的实现也很高效的话,用池就是值得的。
源码是LGPL的(很简单的东西,其实基本上都谈不上什么版权之类的),如果你看源码,会发现这点。
当然欢迎你进一步优化它并共享一哈,呵呵。

>>反复利用同一个xhr在某些平台上可能有问题。
请教会在什么平台什么情况下有问题?
当一个对象被重用的时候,会被open重新初始化的,并且只有当回调函数执行完之后,对象才会被回收。
1 楼 hax 2007-07-21  
1. 反复利用同一个xhr在某些平台上可能有问题。
2. 我个人认为xhr没有必要用池。除非你有足够证据证明创建xhr是很消耗资源的。

相关推荐

    XHR的简单封装xr.zip

    xr 是 XMLHttpRequest 的超简单封装,并返回 ES6 Promise。示例代码:xr.get('/api/items', {take: 5})  .then(res =&gt; console.log(res.data)); xr.post('/api/item', {name: 'hello'})  .then(res =&gt; ...

    深入理解ajax系列第一篇之XHR对象

     ajax技术的核心是XMLHttpRequest对象(简称XHR),这是由微软首先引入的一个特性,其他浏览器提供商后来都提供了相同的实现。XHR为向服务器发送请求和解析服务器响应提供了流畅的接口,能够以异步方式从服务器取得更...

    Ajax-xhr.js.zip

    Ajax-xhr.js.zip,js是使用xmlhttprequest发出ajax/http请求的库()。,ajax代表异步javascript和xml。它是多种web技术的集合,包括html、css、json、xml和javascript。它用于创建动态网页,其中网页的小部分在不重新...

    原生JS封装Ajax插件(同域、jsonp跨域)

    Ajax技术的核心是XMLHttpRequest对象(简称XHR),IE5是第一款引入XHR对象的浏览器,而IE5中的XHR对象是通过MSXML库中的一个ActiveX对象实现的,因此在IE中可能有3个版本,即MSXML2.XMLHttp、MSXML2.XMLHttp.3.0和...

    没有XHR,Ajax精彩依旧

    工作室交流会的ppt,具体是讲通过动态修改html来借用浏览器的实时渲染特性来实现资源的异步下载以及一些应用。

    用原生JS对AJAX做简单封装的实例代码

    首先,我们需要xhr对象。这对我们来说不难,封装成一个函数。 var createAjax = function() { var xhr = null; try { //IE系列浏览器 xhr = new ActiveXObject("microsoft.xmlhttp"); } catch (e1) { try { //非IE...

    对异步请求xhr、ajax、axios、fetch的区别比较

    1. XMLHttpRequest对象 在浏览器中,最开始与服务器交换数据的方式则是通过XMLHttpRequest对象。【它可以使用JSON、XML、HTML和Text文本等格式发送和接收数据。】 优点: 1.不重新加载页面的情况下更新网页 2.在页面...

    Ajax高级笔记 JavaScript高级程序设计笔记

    Ajax的核心:XMLHttpRequest对象(简称XHR) 在XHR对象之前,Ajax通信通常使用hack手段,如使用隐藏的或内嵌的框架。 XHR对象为向服务器发送信息和解析服务器响应提供了流畅的接口。 1.XMLHttpRequest对象 IE5是第一款...

    XHR-Object:一个小的XHR对象,可以轻松地执行XMLHttpRequests

    XHR对象轻松执行XMLHttpRequests的最小XHR对象如何发送POST示例const data = { id : 1 , name : 'Rose'} ;const url = 'test.html' ;xhr . request ( 'POST' , url , data , ( res ) =&gt; { console . log ( res ) ;} ...

    Ajax基础教程之封装(三)

    这个时候,肯定是加一个定时器,然后每隔一段事件,再进行一次Ajax请求,既然要经常用到Ajax请求,封装函数就很必要了,先来看一下上个栗子的js代码,我们来进行封装。 [removed] = function() { var oBtn = ...

    原生Javascript封装的一个AJAX函数分享

    最近的工作中涉及到大量的ajax操作,本来该后台做的事也要我来做了.而现在使用的ajax函数是一个后台人员封装的—-但他又是基于jquery的ajax,所以离开了jquery这个函数就毫无...* Name: xhr,AJAX封装函数 * Description:

    xhr.base:使用xhr调用JQuery ajax

    xhr.base 具有functin的库使用xhr来调用Ajax JQuery。 前提条件 jQuery-3.4.1.min或+ sweetalert2-8.16.3.all.min或+

    ajax兼容所有浏览器详解

    详细介绍了使用ajax如何兼容各种浏览器

    Ajax-tiny-xhr.zip

    Ajax-tiny-xhr.zip,在es6承诺中封装ajax方法的小型库。,ajax代表异步javascript和xml。它是多种web技术的集合,包括html、css、json、xml和javascript。它用于创建动态网页,其中网页的小部分在不重新加载网页的情况...

    Ajax-xhr-chat.zip

    Ajax-xhr-chat.zip,基于ajax xmlhttprequest(xhr)的简单聊天。,ajax代表异步javascript和xml。它是多种web技术的集合,包括html、css、json、xml和javascript。它用于创建动态网页,其中网页的小部分在不重新加载...

    原生js封装的ajax方法示例

    本文实例讲述了原生js封装的ajax方法。分享给大家供大家参考,具体如下: 众所周知,框架之间会有冲突,这是源生js就起到作用了,下面介绍一种源生js封装的ajax请求。 function ajax(options) { ... //创建xhr对象 -

    使用Ext2.0的Ajax连接ArcIMS例子

    使用XHR对象和Ext2.0的Ajax对象给一个ArcIMS服务器发送请求,并返回结果。

    ajax高级程序设计 源代码

    本书是Ajax 领域的名著,详细讲解了帧、JavaScript、cookie、XML 和XHR 如何与Ajax 相关,以及具体的Ajax 技术实现;介绍了各种请求类型,给出了具有一定深度的有关如何以及何时在Web 站点或Web 应用程序中使用Ajax ...

    ajax知识网络图 .xmind格式

    创建XMLHttpRequest对象:var xhr = new XMLHttpRequest(); 给定请求方式与请求地址:xhr.open(“get”,“www.example.com”); 发送请求:xhr.send(); 获取服务器端给客户端的响应数据: xhr.onreadystatechange = ...

Global site tag (gtag.js) - Google Analytics