zoukankan      html  css  js  c++  java
  • B/S架构的进度条原理

      这个星期老大问了我两次同样的一个问题,“CRM批量操作能不能做进度条啊?”,‘CRM’是一套B/S架构的系统;第一次我回答了不能,因为我不想做,第二次我回答可以,说强刷缓冲区就可以了,最后老大又问了CRM的老大,那边又说不可以,哎,我就郁闷了,其实只是人家不想做而已啦。

      好了,背景就这么多了,记下这是ajax请求的做的一个进度条,先说下原理吧,浏览器发出请求到服务器,这里服务器的处理程序的语言我就用PHP吧,请求到了服务器,程序就进行处理返回字符串。一般情况下批量操作都少不了循环吧,好,PHP一个for里面echo。。echo的,这样每次echo浏览器显示的百分数就叠加一下,这样就像进度条了。但是结果不是想的那么如意,而是把全部的echo拼接起来返回了一个字符串,这是为什么呢?是不是echo太快了帮我拼接起来了呢?来个sleep(2);。不如意,结果还是一样,哎,其实就是缓冲区在作怪嘛,本人水平低,只能责怪缓冲区了,当我们用echo或者print_r()输出的时候,被输出的东西并不是马上到了浏览器的,而是被缓冲区存起来了,除非缓冲区满了或者程序结束了才会输出到浏览器,或者命令它输出,哎呀,来啦来啦,原来可以命令输出,事情就简单了,那就有办法叫它每次echo都向浏览器发送内容了,浏览器只要监听它发送回来的东西就解决了。

      这里开始要进入缓冲区讨论了,但是网上很多说没有ob_start()的话,echo都会去浏览器,我试了却不是的,还有很多说用了ob_start()打开,然后ob_end_flush(),就能命令一次发送了,但是我试了之后有时候可以有时候不可以,后来我想想这个太不稳定了吧,不知道是不是版本问题,还是我代码写错了,于是我找到了ob_implicit_flush()这个方法,网上说是强制刷新缓冲区,试了果然每次都可以了,哇,开心啊,解决了,不说废话了,放代码吧。

      这是js的代码,发出ajax请求的(看着就头晕是吧)

    简单解析下,其中有用到ext js的MessageBox,还有大家不用管gblPageTabObject[gblCurrentTabName].,因为这个系统的多页签,所以才用这个的,当做是一个变量就可以了,

    gblPageTabObject[gblCurrentTabName].msgBox = Ext.MessageBox;//定义全局,不然会闪的
    gblPageTabObject[gblCurrentTabName].msgv = 0;//返回的进度变量
    gblPageTabObject[gblCurrentTabName].count = 20;//进度条的总值,视各自情况而定

    //按钮的触发函数(onclick=”gblPageTabObject[gblCurrentTabName].testWin()“),只管这个函数,都面的是被调用
    gblPageTabObject[gblCurrentTabName].testWin=function()
    {
      gblPageTabObject[gblCurrentTabName].msgv = 0;
      xmlHttp=GetXmlHttpObject();
      if (xmlHttp==null)
      {
        alert ("Browser does not support HTTP Request");
        return;
      }
      var url="/cust/test/test3.php?count="+gblPageTabObject[gblCurrentTabName].count;
      xmlHttp.onreadystatechange=stateChanged;//请求后的监听函数
      xmlHttp.open("GET",url,true);
      xmlHttp.send(null);
      msgBoxShow(gblPageTabObject[gblCurrentTabName].msgv,gblPageTabObject[gblCurrentTabName].count);//显示进度条
    }

    //监听函数
    function stateChanged()
    {

      //xmlHttp.responseText,返回的结果,大家都知道的
      if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete")
      {
        var obj = xmlHttp.responseText;
        alert(obj);
        gblPageTabObject[gblCurrentTabName].msgBox.hide();
      }
      if (xmlHttp.readyState==3)
      {
        var obj = xmlHttp.responseText;
        arr=obj.split("-");
        gblPageTabObject[gblCurrentTabName].msgv = arr[arr.length-1];
        msgBoxShow(gblPageTabObject[gblCurrentTabName].msgv,gblPageTabObject[gblCurrentTabName].count);

        //alert(obj);
      }
    }

    //显示进度条,ext的控件,progress,updateProgress方法
    function msgBoxShow(msgv,count){
      v = msgv;
      gblPageTabObject[gblCurrentTabName].msgBox.progress("请等待", "数据处理进度...'");
      gblPageTabObject[gblCurrentTabName].msgBox.updateProgress(v/count,v/count+"已完成");
    }

    //创建请求对象
    function GetXmlHttpObject()
    {
      var xmlHttp=null;
      try
      {
        // Firefox, Opera 8.0+, Safari
        xmlHttp=new XMLHttpRequest();
      }
      catch (e)
      {
        // Internet Explorer
        try
        {
          xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
        }
        catch (e)
        {
          xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
        }
      }
      return xmlHttp;
    }

    好了,请求发送出去了,到服务器处理了,一下才是关键,原理所在啊,不过只要一点代码

    <?php
    $result->success='success';
    $result->msg='aaa';
    $v=0;
    ob_implicit_flush();//强制刷新,让服务器向浏览器发送内容
    ob_start();
    $count = $_GET["count"];
    for($i=0;$i<$count;$i++)
    {
      if($i==$v)
      {
      //ob_end_clean();
      //if($i==2||$i==5)
      // sleep(2);
      sleep(1);
      //echo json_encode($result);
      ob_end_clean();
      echo '-'.$i;
      ob_end_flush();//让服务器向浏览器发送内容,很奇怪这句话有时候没有也可以,不知道是不是我用虚拟机的问题
      //ob_end_clean();
      ob_start();
    }
    $v++;
    }
    ?>

    效果图:

    总感觉里面有很多代码是多余的,大家自己剪掉吧,各自可以进行具体测试。原理就是刷缓冲区,其它语言应该也差不多吧,本人水平只能理解到这个了,如果大家知道的是其它技术的话,一起讨论下,别私藏啊,回复告诉我哦。

  • 相关阅读:
    android开发里遇到的坑——eclipse项目导入android studio以后Run按钮灰色
    升级完Android Studio3.2后,打包release出现的错误
    Android Studio升级到3.0,抛出Aapt2Exception异常
    android开发里跳过的坑——camera调用setDisplayOrientation设置预览显示旋转无效
    HTTP错误:java.lang.IllegalArgumentException: Illegal character in scheme at index 0: http://xxxxxx
    6572平台上关于wifi热点切换跳的坑
    Error:Uninitialized object exists on backward branch 70 Exception Details:
    [转]android 如何获取第三方app的sha1值
    如何在Ubuntu 20.04 LTS服务器上安装Virtualmin
    如何在Ubuntu 20.04 LTS上安装Apache Hadoop?
  • 原文地址:https://www.cnblogs.com/huanlinll/p/2835259.html
Copyright © 2011-2022 走看看