一尘不染

在进程运行时更新网页

ajax

我有一个页面,其中发生了许多耗时的功能。我想做的是在过程的每个步骤完成后,更新网页以使用户知道刚刚完成的步骤。本质上,用户提交查询,然后服务器查询数据库,处理数据,绘制图像并在页面上显示结果。我想让网页说出该功能执行的步骤。它会说“先查询”然后“正在处理”
…等等。

伪:

protected void Search(object sender, EventArgs e){

    //display that the process has begun
    List queryResults = Query()
    //display that the query is finished
    foreach(item in queryResults){
       ProcessItem(item)
       //display that item has been processed
       Render(item)
       //display item has been rendered
    }

}

我已经研究过使用Ajax来更新页面而不重新加载它,但是根据我的简单理解(对Ajax零经验),客户端将向服务器请求文件。我需要Ajax工具吗?如果是这样,这是否意味着我将在受评论的区域中向客户端发送一个ajax响应?


阅读 172

收藏
2020-07-26

共1个答案

一尘不染

Web服务器无法将未经请求的数据推送到客户端。他们服从请求-响应周期。另一种方法是使用消息队列,但会大大增加复杂性。

从客户端轮询还不错。Web服务器擅长处理许多短请求,并且2到3秒的轮询间隔应该足够快。

这是我喜欢使用的一种轮询方法。它异步等待响应返回,然后再次轮询(需要jQuery):

function poll(url, task, progressBar, resultsCallback, 
        timeoutMillis, pollIntervalMillis) {
    $.ajax({
        url: url,
        type: 'GET',
        dataType: 'json',
        timeout: timeoutMillis,
        data: 'action=poll&task='+task,
        success: (function(response, status, xhr) {
            if ('progress' in response) {

                // update the UI with the progress
                progressBar.setValue(response.progress);
            }
            if ('status' in response) {
                if (response.status == 'pending') {

                    // task is not finished, continue polling
                    setTimeout((function() {
                        poll(url, task, progressBar, resultsCallback, 
                                timeoutMillis, pollIntervalMillis);
                    }), pollIntervalMillis);
                }
                else {

                    // task completed
                    if (response.status == 'cancelled') {
                        progressBar.setColor('red');
                        progressBar.setText("Task '"+task+"' was cancelled");
                    }
                    else {
                        progressBar.setColor('green');
                        progressBar.setText("Task '"+task+"' complete");
                    }

                    // GET the results
                    $.ajax({
                        url: url,
                        type: 'GET',
                        timeout: timeoutMillis,
                        data: 'action=results&task='+task,
                        success: (function(response, status, xhr) {
                            resultsCallback(response, status, xhr);
                        }),
                        error: error
                    });
                }
            }
        }),
        error: error
    });

    function error(xhr, status, err) {
        alert('Failure to communicate with server: ' + status + ', ' + err);
    }
}

并且您的服务器端代码应使用以下内容响应轮询:

{"progress" : 42, "status" : "pending"}
2020-07-26