2010-09-11 5 views
0

J'ai une démo utilisant jQuery ajax pour appeler le service web, en même temps, une autre requête montre la progression.comment montrer le progrès immédiatement en utilisant ajax?

Pourquoi ne pas afficher le progrès immédiatement, tandis que le dernier pour montrer toute la progression. Le code comme ceci: WebService.ashx (C#):

public class WebService : IHttpHandler 
{ 
    public void ProcessRequest(HttpContext context) 
    { 
     string invoke = string.Empty; 
     string jsoncallback = string.Empty; 

     if (!string.IsNullOrEmpty(context.Request["invoke"])) 
      invoke = context.Request["invoke"].ToString().Trim(); 
     if (!string.IsNullOrEmpty(context.Request["jsoncallback"])) 
      jsoncallback = context.Request["jsoncallback"].ToString().Trim(); 

     context.Response.ContentType = "application/x-javascript; charset=utf-8"; 
     switch (invoke.ToLower()) 
     { 
      case "call": 
       int currentValue = 0; 
       int TotalValue = 100; 
       HttpContext.Current.Cache.Remove("progress"); 
       HttpContext.Current.Cache.Insert("progress", currentValue + "," + TotalValue, null, 
        DateTime.Now.AddMinutes(60),System.Web.Caching.Cache.NoSlidingExpiration); 

       for (int i = 1; i <= TotalValue; i++) 
       { 
        currentValue = i; 
        //TODO... 
        HttpContext.Current.Cache.Insert("progress", currentValue + "," + TotalValue, null, 
         DateTime.Now.AddMinutes(60), System.Web.Caching.Cache.NoSlidingExpiration); 
        Thread.Sleep(100); 
       } 
       context.Response.Write(string.Format("{0}({{error:{1}, message:\"{2}\"}})", jsoncallback, false.ToString().ToLower(), "finished.")); 
       break; 
      case "progress": 
       string progress = "100,100"; 
       if(HttpContext.Current.Cache["progress"] != null) 
       { 
        progress = HttpContext.Current.Cache["progress"].ToString(); 
       } 
       context.Response.Write(string.Format("{0}({{error:{1}, message:\"{2}\"}})", jsoncallback, false.ToString().ToLower(), progress)); 
       break; 
      default: 
       context.Response.Write(string.Format("{0}({{error:{1}, message:\"{2}\"}})", jsoncallback, false.ToString().ToLower(), "parameter error.")); 
       break; 
     } 
    } 

    public bool IsReusable 
    { 
     get{return false;} 
    } 
} 

et la page:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> 
<style> 
    .ProgressBar { 
     position:relative; 
     margin-top:30px; 
     margin-bottom:20px; 
     margin-left:240px; 
     width: 220px; 
     border: 1px solid #B1B1B1; 
     overflow: hidden; 
    } 
    .ProgressBar div { 
     position:relative; 
     background: #2BD029; 
     color: #333333; 
     height: 15px; 
     line-height: 15px; 
     text-align:left; 
    } 
    .ProgressBar div span { 
     position:absolute; 
     width: 220px; 
     text-align: center; 
     font-weight: bold; 
    } 
</style> 
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> 
<script type="text/javascript"> 
    var intervalID; 

    function RequestProcess(){ 
     $.getJSON("http://localhost:4397/webservice.ashx?invoke=progress&jsoncallback=?", function(data) { 
      var progress = data.message; 
      var position = parseInt(progress.split(",")[0]/progress.split(",")[1] * 100);   
      if(isNaN(position)) 
       position = 0; 
      $('#divMessage').append("<br/>"+position); 
      if (position >= 100) stopRequestProcess(); 
      $('.ProgressBar > div').css({ "width": position + "%" }); 
      $('.ProgressBar > div > span').html(position + "%"); 
      $('#ProgressInfo').html(position >= 100 ? "finished" : position); 
     }); 
    } 
    function stopRequestProcess(){ 
     clearInterval(intervalID); 
    } 

    $(document).ready(function(){ 
     $('#btnStart').click(function(){ 
      $('#divMessage').html(''); 
      $.ajax({ 
       type: "GET", 
       url: "http://localhost:4397/webservice.ashx?invoke=call&jsoncallback=?", 
       dataType: "jsonp", 
       async: false, 
       error: function(xhr, ajaxOptions, thrownError) { 
        stopRequestProcess(); 
       }, 
       success: function(response) { 
        stopRequestProcess(); 
        $('.ProgressBar > div').css({ "width": "100%" }); 
        $('.ProgressBar > div > span').html("100%"); 
        $('#ProgressInfo').html("finished"); 
       } 
      }); 

      intervalID = setInterval(RequestProcess, 500); 
     }); 
    }); 
</script> 
</head> 

<body> 
     <div> 
      <div> 
       <div class="ProgressBar" style="*margin-left:0px" align="left"> 
        <div style="width:0%;*margin-left:0px"><span>0%</span></div> 
       </div> 
       <div id="ProgressInfo" class="ProgressInfo">processing...</div> 
      </div> 
      <button id="btnStart" name="btnStart">start</button> 
     </div> 
     <br/>Progress Information:<br/> 
     <div id="divMessage"></div> 
</body> 
</html> 
+0

code html: http://net205.myhost21.com/images/ProgressDemo.txt l'instantané: http://net205.myhost21.com/images/progress.jpg – Net205

Répondre

1

Couple de remarques au sujet de votre code:

  1. Vous devez commencer une nouveau thread pour effectuer l'opération longue et retourner immédiatement et ne pas bloquer le thread de travail
  2. Vous utilisez le cache pour tra progrès ck, ce qui n'est pas fiable. ASP.NET peut expulser le cache dans des circonstances différentes, comme par exemple à court de mémoire, etc ...

Voici un exemple que j'ai mis:

public class WebService : IHttpHandler 
{ 
    public void ProcessRequest(HttpContext context) 
    { 
     context.Response.ContentType = "application/x-javascript"; 
     var id = context.Request["id"]; 

     if (string.IsNullOrEmpty(id)) 
     { 
      id = Guid.NewGuid().ToString(); 
      context.Application[id] = 0; 
      new Thread(() => 
      { 
       for (int progress = 0; progress < 100; progress++) 
       { 
        context.Application[id] = progress; 
        Thread.Sleep(100); 
       } 
       context.Application.Remove(id); 
      }).Start(); 
     } 

     var serializer = new JavaScriptSerializer(); 
     context.Response.Write(serializer.Serialize(new 
     { 
      id = id, 
      error = false, 
      progress = context.Application[id] ?? 100 
     })); 
    } 

    public bool IsReusable 
    { 
     get { return false; } 
    } 
} 

Et le client:

<!DOCTYPE html> 
<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> 
<title>Test</title> 
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> 
<script type="text/javascript"> 
    var intervalId = null; 
    $(function() { 
     $('button').click(function() { 
      $(this).attr('disabled', 'disabled').text('processing...'); 
      $.getJSON('/webservice.ashx', function (result) { 
       intervalId = setInterval(function() { 
        poll(result.id); 
       }, 1000); 
      }); 

     }); 
    }); 

    function poll(taskId) { 
     $.getJSON('/webservice.ashx', { id: taskId }, function (result) { 
      if (result.progress >= 100) { 
       clearInterval(intervalId); 
       $('button').removeAttr('disabled').text('start'); 
      } 
      $('#progress').html(result.progress + '%'); 
     }); 
    } 
</script> 
</head> 
<body> 
    <button>start</button> 
    <div id="progress"></div> 
</body> 
</html> 
+0

salut, Darin Dimitrov, je testé votre code a eu quelques problèmes, et j'ai modifié un peu de code support jsonp, ça marche bien, merci beaucoup! code: chaîne jsoncallback = chaîne.Empty; if (! String.IsNullOrEmpty (context.Request ["jsoncallback"])) jsoncallback = context.Request ["jsoncallback"]. ToString(). Trim(); // .... context.Response.Write (jsoncallback + "(" + serializer.Serialize (nouveau { id = id, erreur = false, progress = context.Application [id] ?? 100 }) + ")"); – Net205

+0

'/webservice.ashx' -> '/webservice.ashx?jsoncallback=?' – Net205

Questions connexes