Your Ad Here
首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 网站建设 > 网页制作 > 诊断并解决ajax异步调用产生的后遗症
【标  题】:诊断并解决ajax异步调用产生的后遗症
【关键字】:ajax
【来  源】:http://blog.csdn.net/terrykingcha/archive/2006/11/05/1367669.aspx

诊断并解决ajax异步调用产生的后遗症

Your Ad Here

       终所周知,在使用xmlHttpRequest进行异步调用时,浏览器会给每个请求分配一个独立线程(进程?没细去研究) ,当请求成功(或者失败后)再响应回调函数。当遇到某些ui部分的操作必须等在异步请求结束后才能进行的情况下,一般处理方式有两种:1、把界面部分的操作函数做为回调函数;2、改用同步模式。先来批判下第二种方法,这样无疑失去了ajax精髓的部分,所以不提倡。那么第一种方法呢?举个例子,对界面部分的操作写成了一个类,通过类的方法来进行调用,那此时,不得不把类的初始化,类的方法调用写到回调函数里。再举个例子,直接在这个类里编写实现异步调用的方法(也就是异步调用和ui操作是同一个类的不同方法)。虽然,这些都是普遍的做法,但是,这恰恰已经使界面操作和控制器部分混合在了一起,不符合mvc的思想,当然也并不利于重用。

       那如何来解决这个后遗症呢?设想下,问题是必须等到异步调用结束后,才能进行相应的其他操作,那么如果,设立一个独立的进程来检查异步调用是否已经结束,当结束后通知需要进行操作的方法再来执行。注意,这和用同步调用是有区别的。因为同步调用是阻塞了整个浏览器的进程。而这种用独立进程来检查的方式,并不影响其他异步调用。为此我对症下葯,实现了如下这个类:(需要prototype框架支持)

 

var xRouter=Class.create();
xRouter
={
    routers:[],     
/*数组,用于存放请求*/
    
    
/*注册请求,第一个参数为类实例或者函数引用,第二参数指示该请求的行为,是异步处理还是同步处理*/
    
/*
        如果请求是类,类中必须实现load方法,用来启动类的各种操作,并且如需要进行同步处理时,
        在适当的位置赋state字段为‘complete’,来指示此类已经调用结束。
    
*/
    register:
function(application,asy) {
        
if (!asy) asy=false;
        Object.extend(application,{$__asy:asy});
        
if (!this.routers.include(application))
            
this.routers.push(application);
    },
    
    
/*
        注销请求,注意,请求必须是类的实例引用或者已声明函数的引用
    
*/    
    unregister:
function(application) {
        
this.routers=this.routers.without(Object.extend(application,{$__asy:true}));
        
this.routers=this.routers.without(Object.extend(application,{$__asy:false}));
    },
    
    
/*
        轮讯各个请求,实现各个请求的异步调用和同步调用
    
*/    
    dispatch:
function() {
        
this.routers.findAll(function(app){
                
return (app.$__asy);
            }).each(
function(app) {
                
if (typeof app=='object')
                {
                    app.load();
                }
                
else if(typeof app=='function')
                {
                    app.call(
this);
                }
                
this.unregister(app);
            }.bind(
this));
        
this.router();
    },

    
/*内部函数,当注册的请求没有需要异步处理时,用户也可以直接调用此函数进行同步处理*/
    router:
function() {
        
if (this.routers.length>0)
        {
            
var app=this.routers.shift();
            
if (typeof app=='function' && !app.$__asy)
            {
                app.call(
this);
                
this.router();
            }
            
else if (typeof app=='object' && !app.$__asy)
            {
                app.load();
                app.base
=this;                             /*绑定this对象,以便其后调用*/
                setTimeout(
this.checkState.bind(app),1);   /*用单独线程检查类的异步调用是否完成*/
            }
            
else
            {
                
this.router();
            }
        }
    },
    
    checkState:
function() {
        
if (this.state && this.state.toLowerCase()=='complete')
            
this.base.router();    /*如果类的异步调用已经完成,则继续下一个需要同步处理的类或者函数*/
        
else
            setTimeout(
this.base.checkState.bind(this),1);   /*否则,继续检查*/
    }
};

 

 为了更加直观的理解此方法,下面再重新组织一下xmlHttpRequest(同样需要prototype框架支持)

 

var xLoader=Class.create();
xLoader.prototype
={
    initialize:
function(url,options) {
        
this.url=url;                 /*请求后台模型或者页面的地址*/
        
this.options=Object.extend{
            {
                method:
'get',
                parameters:
null
            }
            ,options 
|| {});          /*用户自定义参数*/
        
this.loader=null;             /*xmlHttpRequest请求加载实例*/
        
this.state=null;              /*类当前状态*/
        
this.isSuccess=false;         /*指示异步调用是否成功*/
        
this.request;                 /*返回的request对象*/
    },
    
    
/*类启动*/
    load:
function() {
        
var url=jsEvent.noCache(this.url);   /*一个防止页面缓存的处理函数,可以忽略*/
        
this.loader=new Ajax.Request(
            url,
            {
                method:
this.options.method,
                parameters:
this.options.parameters,
                onSuccess:
this.successHandler.bind(this),
                onFailure:
this.failureHandler.bind(this)
            }
        );
    },
    
    successHandler:
function(request) {
        
this.isSuccess=true;
        
if (this.options.onSuccess) this.options.onSuccess.call(this,request);   /*调用用户自定义的函数*/
        
this.completeHandler();
    },
    
    failureHandler:
function(request) {
        
this.isSuccess=false;
        
if (this.options.onFailure) this.options.onFailure.call(this,request);   /*调用用户自定义的函数*/
        
this.completeHandler();
    },
    
    completeHandler:
function(request) {
        
if (this.options.onComplete) this.options.onComplete.call(this,request); /*调用用户自定义的函数*/
        
this.request=request;                                                    
        
this.state=Ajax.Request.Events[this.loader.transport.readyState];        /*记录类的状态为complete*/
    }
};

 

举例:

 

<script type="text/javascript" src="lib/prototype-1.4.0.js"></script> <!--需要prototype框架支持-->
<script type="text/javascript">
//<![CDATA[
    var xmlDoc;       
    
    window.onload
=function() {
        xRouter.register(
new xLoader('test1.xml',{onComplete:test1}),false);
        xRouter.register(
new xLoader('test2.xml',{onComplete:test2}),true);
        xRouter.register(test3,
true);
        xRouter.register(test4,
false);
        
/*按照注册请求的顺序,处理其中需要同步处理的请求*/
        xRouter.dispatch();
    }
    
    
function test1(request) {
        alert(
'同步处理对test1.xml的异步请求');
        xmlDoc
=request.responseXML;
    }
    
    
function test2() {
        alert(
'异步处理对test1.xml的异步请求');
    }
    
    
function test3() {
        alert(
'异步处理test3函数');
    }
    
    
var test4=Class.create();
    test4.prototype
={
        initialize:
function() {
            alert(
'同步处理对test1.xml异步请求结束后的test4类');
            
this.state=null;
        },
        
        load:
function() {
            alert(xmlDoc.xml);
            
this.state='complete';
        }
    }
//]]>
</script>
客户端方便操作cookies的类:【上一篇】
MagicLinux2.0下配置Ruby on Rails开发环境:【下一篇】
【相关文章】
  • AJAX设计策略(全)
  • Microsoft Ajax Beta1 - 边学边用边补充 (Part 4 - $create)
  • 不可多得的Javascript(AJAX)开发工具 - Aptana
  • AJAX实例1--数据检验
  • AJax实例2--级联菜单
  • Ajax正在成为Web开发的基础
  • 关注AJAX(5): Apollo,Timeline Widget,ASP.NET AJAX动画效果
  • AJAX设计策略(九)
  • Ajax 学习心得
  • 关注AJAX(4):ComponentArt,母板页和定制UpdateProgress
  • 【随机文章】
  • 安装类型
  • 禁止使用IE“internet选项”中的“安全”菜单
  • 详解Linux安全管理的基本技巧
  • 编程输出如下字符图形(2种方法)
  • 浅析ASP内置组件
  • 两分钟让你明白什么是ERP
  • ASP.NET中处理datetime的一些通用函数
  • rfc793中文翻译四(dlmu2001)
  • 学无止境
  • 买了edong的空间没有db_securityadmin权限
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 bbb软讯网络 All Rigths Reserved.