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++;
}
?>

 

效果圖:

總感覺里面有很多代碼是多余的,大家自己剪掉吧,各自可以進行具體測試。原理就是刷緩沖區,其它語言應該也差不多吧,本人水平只能理解到這個了,如果大家知道的是其它技術的話,一起討論下,別私藏啊,回復告訴我哦。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM