如何使用ajax立即显示进度?

发布于 2024-09-18 07:57:34 字数 5721 浏览 1 评论 0原文

我有一个使用 jQuery ajax 调用 Web 服务的演示,同时另一个请求显示进度。

为什么它不立即显示进度,而最后显示所有进度。 代码是这样的: 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;}
    }
}

以及页面:

 <!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>

I have a demo using jQuery ajax to invoke web service,at the same time,another of a request shows the progress.

Why it not show progress immediately, while the last to show all the progress.
The code like this:
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;}
    }
}

and the 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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

顾挽 2024-09-25 07:57:35

关于您的代码的几点说明:

  1. 您需要启动一个新线程来执行冗长的操作并立即返回,而不是阻塞工作线程
  2. 您正在使用缓存来跟踪进度,这是不可靠的。 ASP.NET 可以在不同情况下逐出缓存,例如内存不足等...

这是我放置的一个示例:

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

客户端:

<!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>

Couple of remarks about your code:

  1. You need to start a new thread to perform the lengthy operation and return immediately and not block the worker thread
  2. You are using the cache to track progress, which is not reliable. ASP.NET can evict the cache under different circumstances like for example running low on memory, etc...

Here's an example I've put:

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

And the 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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文