zoukankan      html  css  js  c++  java
  • Qomolangma框架库(三):处理池与处理机

    ================================================================================
    Qomolangma OpenProject v1.0


    类别    :Rich Web Client
    关键词  :JS OOP,JS Framwork, Rich Web Client,RIA,Web Component,
              DOM,DTHML,CSS,JavaScript,JScript

    项目发起:aimingoo (aim@263.net)
    项目团队:../../Qomo_team.txt
    有贡献者:JingYu(zjy@cnpack.org)
    ================================================================================


    一、框架库:处理池与处理机
    ~~~~~~~~~~~~~~~~~~
    严格地说,Pool被译成“池”即可,只是在Qomo的TPool类中,所有放在“池”中的对象都是
    处理机(Machine),因此这个TPool被称为“处理池”类。

    Pool的出现早在WEUI的时代,其目的是处理同步的、缓存的XmlHttp对象。因此,Machine也
    就在事实上只实现了“THttpGetMachine”。这个HttpGetMachine也能处理POST类型的HTTP请
    求,所以,严格地说,它应该名为“THttpMachine”。

    Pool是一种机制,并不局限在使用 HttpGetMachine 上。HttpGetMachine只是Machine的一个
    实现实例。我们先澄清这一点,以避免开发人员把它当成了Ajax技术的另一个名词。

    HttpGetMachine已经处理了兼容问题。随便指出,Framework/Common下的公共类,都是可以
    在mozilla兼容浏览器中使用的。


    二、池化的架构
    ~~~~~~~~~~~~~~~~~~
    Pool提供四种能力:
      - 注册处理机类(Machine Class)
      - 管理处理机实例(Machine Instance)
      - 调度处理机(包括状态:resume, sleep, free)
      - 管理数据(Data)对象

    处理机类提供处理数据(Data)的能力,数据(Data)的结构对Pool来说是完全透明,Pool只在
    调度过程中,将数据传给处理器,处理器如何识别、使用、修改这个数据,Pool完全不知。

    处理机应当具体的能力有:
      - 提供 OnStateChange 事件,响应来自Pool的调度状态(resume, free)
      - 在必要的时候,激活OnStateChange事件,以通知Pool进入调度状态(sleep)

    事实上,Pool和Machine都可以响应三种状态,架构中没有约定哪种状态由谁发出,或者是由
    谁处理(并终结)。但在目前的设计中,
      - Machine处理完一段事务后,(类似于线程一样,)应触发sleep状态.
      - Pool在调用push()方法填入新的数据时,如果有空闲的Machine,则触发该Machine的result;
        否则,(在Pool未满的情况下,将)尝试创建新的Machine,会触发它Machine的resume.
      - Machine处理完自己的事务并进入sleep状态时,如果Pool有未处理数据,则为该Machine
        触发一个新的resume.

    Pool和Machine可以根据需要重新设定触发方式,但不能改变对各状态值的含义的约定。

    Pool和Machine都可以添加新的状态。

    Machine的启动时间,以及Data处理的结束时间,是没有时序和关联的。


    三、使用处理池
    ~~~~~~~~~~~~~~~~~~
    同一个处理池中,只能使用相同的处理机。这在处理池创建时就需要定义好。例如:
    ------------------
    // 声明一个处理THttpGetMachine的池,池的大小(深度)为10
    var pool = new Pool(THttpGetMachine, 10);
    ------------------

    这里,池的大小为10表明池中容纳THttpGetMachine实例的上限为10个。当Machine在忙(Busy)时,
    如果有新的数据请求处理,则会尝试创建新的Machine。当上限设定数的Machine都在忙时,数据
    被缓存到队列中等待处理。

    从原理上来说,无论是创建大小为1个还是100个的池,最终所有的数据都能得到处理。只是处理
    的并发量不一样,因此速度和性能也就有差异。——池的大小通常是经验值。

    池创建后立即开始工作。但它只响应一个方法:
    ------------------
    pool.push( _your_data );
    ------------------

    这里的_your_data是用户自已决定的一种结构,它对于Pool来说是透明的。当它被处理时,会被
    传递到某个Machine实例,而这个实例确切地知道如何处理这种数据。

    对于THttpGetMachine来说,它能处理一个对象,该对象有一个名为src的属性,即:
    ------------------
    var data = { src: "
    http://www.doany.net/" };
    pool.push( data );
    ------------------

    这里并不限制必须是一个对象,也不限制必须是直接量声明。当然,直接量的好处,是你可以这
    样写代码:
    ------------------
    pool.push({ src: "
    http://www.doany.net/" });
    ------------------


    四、使用处理机
    ~~~~~~~~~~~~~~~~~~
    如何处理机被实现过,那么使用者只需要非常简单地调用,即可完成处理,而无需关注具体的处
    理机与处理池的调度过程。在上面这个使用THttpGetMachine的例子中,我们的基本代码如下:
    ------------------
    // 1. 处理数据时的动作
    function doAction(state) {
      // THttpGetMachine约定state值4表明下载完毕
      if (state == 4) {
        alert('Url: %s/nLength: %s'.format(this.data.src, this.get('XMLHTTP').responseText.length));
      }
    }

    // 2. Pool的状态变更响应
    function doOnStateChange(mac, state) {
      doAction.call(mac, state);
    }

    // 3. 创建pool并添加事件响应
    var pool = new Pool(THttpGetMachine, 10);
    pool.OnStateChange.add(doOnStateChange);

    // 4. 处理数据
    pool.push({ src: "
    http://www.doany.net/" });
    ------------------

    上面的步骤1、2可以有更灵活的处理方式,包括"this"的传递、数据(Data)的分析、状态(State)
    的识别等等,这些都是用户代码中的技巧。但在THttpGetMachine中,基本的使用方法是如上的。

    下面讲述处理机的实现方法。因为Qomo的框架允许用户自行扩充各种不同的处理机。


    四、实现处理机(1):基本结构
    ~~~~~~~~~~~~~~~~~~
    处理机需要具有两个属性:
      - data: 当处理机被TPool调度时,data指向需要被处理的数据
      - pool: 当处理机被TPool调度时,pool指向Pool自身

    所以我们看到,THttpGetMachine实现中,为每个对象声明了这两个属性:
    ------------------
    function HttpGetMachine () {
      //...
     
      this.Create = function() {
        this.data = null;
        this.pool = null;

        // ...
      }
    }
    ------------------

    我们说过,处理机明确地知道它将处理的数据的格式。因此,在THttpGetMachine的实现中,它
    响应OnStateChange时的处理代码如下:
    ------------------
    var doStateChange = function(state) {
      if (state=='resume') {
        // 获取或创建 XmlHttpRequest 对象、设置属性等
        var xmlHttp = ...
        var method = 'GET';

        // this 指向 Machine 自身
        var src = this.data.src;

        // src 指向需要当前 Machine 处理的URL地址,因此应该通过类似如下代码来获取数据
        xmlHttp.open(method, src, true);
        xmlHttp.send(null);
      }
      else if (state=='free') {
        // ...
      }
    }
    ------------------


    五、实现处理机(2):自定义状态
    ~~~~~~~~~~~~~~~~~~
    我们发现,这里的代码中,只处理了XmlHttpRequest开始下载的行为,那么这个对象下载完成
    之后应该如何处理呢?

    对于XmlHttpRequest来说,同步调用时,onreadystatechange事件会被对象触发。而这个状态其
    实对Pool来说,是透明的。这时,Pool会把这个状态交回给Machine。这个过程在Pool和Machine
    中传递,但只被Machine处理。

    这些状态,被称为自定义状态——例如前面提到过的状态值“4”。它们是由Machine负责处理的。
    THttpGetMachine使用如下的方法来实现自定义状态:
    ------------------
    // 定义XMLHTTP.onreadystatechange事件的响应句柄
    var onreadystatechange = function() {
      var xmlHttp = this.get('XMLHTTP');

      this.OnStateChange(xmlHttp.readyState);

      if (xmlHttp.readyState==4) {
        this.OnStateChange('sleep')
      }
    }

    // HttpGetMachine的对象构造过程
      this.Create = function() {
        //..

        var ajx = new Ajax();
        var mac = this;
        this.set('XMLHTTP', ajx);

        // 将函数封装为方法,以使this在函数内有效
        this.get('XMLHTTP').onreadystatechange = function() {
          onreadystatechange.apply(mac, arguments);
        }
      }
    ------------------

    我们看到,HttpGetMachine内部处理了XmlHttpRequest对象的状态变更,并通过调用
    ------------------
      this.OnStateChange(xmlHttp.readyState);
    ------------------

    来向处理器自身/子类/事件处理程序传递该状态,同时Pool也会感知到这个事件并响应它。

    这样,xmlHttp.readyState这个自定义状态就成功地在架构的全局完成了传递——如果有事件
    处理程序需要处理这个状态的话,就可以得到响应的机会。

    onreadystatechange中有一段代码用于激活处理机的"sleep"状态。因为这个xmlHttp已经完成
    了它的“处理任务”,也就是获取数据。而且,完成下载的状态值“4”也经在上一行代码中
    向架构全局发布了通知,这意味着(如果有响应者的话)已经完成了处理过程。所以这里触发
    了"sleep"状态。

    上面的代码与Qomo代码包中稍有差距。代码包中的_changer()函数用于封装这个过程,而原因
    只是因为在Mozilla引擎中,xmlHttp.onreadystatechange会在处理完成后被自动置null。


    六、处理机的高级使用方法
    ~~~~~~~~~~~~~~~~~~
    Qomo的类继承结构允许你进一步的实现THttpGetMachine的子类,或者创建新的Machine类,以
    处理其它的数据。一般来讲,你不必要重写Pool。

    在前面的基本用法中,数据的处理程序是挂在Pool.OnStateChange事件上的。但这并不是理想
    的用法,事实上,处理的最终处理应当由Machine负责。因此,下面的代码更符合逻辑:
    ------------------
    function MyMachine() {
      var doStateChange = function(mac, state) {
        // if (state == 4) ...
        // ...
      }

      this.Create = function() {
        this.OnStateChange.add(doStateChange);
      }
    }

    TMyMachine = Class(THttpGetMahine, 'MyMachine');


    var pool = new Pool(TMyMachine, 10);
    //...
    ------------------

    也许你还不明白这种结构的价值,那么下面的例子,讲述如何处理不同的网页。——事实上,
    这已经实现了一个动态获取并分析网页(搜索引擎?)的基本结构,或者你也可以用它来做
    RSS分析。
    ------------------
      var analy_tree = {
        sina: function(ctx) {
          // ...
        },

        baidu: function(ctx) {
          // ...
        },

        google = function(ctx) {
          // ...
        }
      };

      funtion getHostFromUrl() {
        // 分析URL,对不同的url返回其host,或返回特定的分析器标识(analy_tree的属性名)
      }

      var doStateChange = function(mac, state) {
        if (state != 4) return;

        var host = getHostFromUrl(this.data.src);
        var analizer = analy_tree[host];
        if (analizer) {
          analizer.call(this, this.get('XMLHTTP').responseText);
        }
      }
    ------------------

    更多的代码,我就不写了。哈哈~~


    七、其它
    ~~~~~~~~~~~~~~~~~~
    详见示例:
      /Framework/DOCUMENTs/TestCase/T_Ajax.html

    这个示例是可以运行在FireFox等Mozilla系列浏览器上的。但由于有跨域数据存取的问题(我在
    示例中访问了非本机的Url),因此你可能会看到一个警告框,请确定即可。

    在这个文件:
      /Framework/DOCUMENTs/TestCase/T_AjaxPriviledge(FF).html

    中是一个解释mozilla系列浏览器上跨域存取的示例。但目前来说,没有方法能清除那个提示框。

    ^.^ 

  • 相关阅读:
    Java 书籍 Top 10
    maven学习笔记
    Extjs study
    初学spring mvc
    spring context:componentscan (转)
    What is AspectJ(转)
    java concurrency 学习
    (转)深入浅出REST
    icloud不用翻就能显示地图的办法(转)
    OSGi知识
  • 原文地址:https://www.cnblogs.com/encounter/p/2188687.html
Copyright © 2011-2022 走看看