Jquery 长ajax查询中进度条的更新模式

Jquery 长ajax查询中进度条的更新模式,jquery,ajax,node.js,progress-bar,Jquery,Ajax,Node.js,Progress Bar,以下是我所拥有的: 执行长(2-10秒)计算(db+外部API调用)的Node.js函数。我使用async.auto()来组织调用的依赖关系 HTML视图页面上的一个漂亮的可视进度条 调用查询的getJSON函数(参见下面的代码) 现在,我正在更新计时器上的进度条。但我希望它更准确。我已经将服务器端功能中断为5个里程碑(即,在每个外部调用成功完成后),我想将该进度信息发送给客户端。但是,一旦您res.send(progress)完成了响应,就不能再发送任何内容了 我显然需要一个不同的模式,我有一

以下是我所拥有的:

  • 执行长(2-10秒)计算(db+外部API调用)的Node.js函数。我使用
    async.auto()
    来组织调用的依赖关系
  • HTML视图页面上的一个漂亮的可视进度条
  • 调用查询的getJSON函数(参见下面的代码)
  • 现在,我正在更新计时器上的进度条。但我希望它更准确。我已经将服务器端功能中断为5个里程碑(即,在每个外部调用成功完成后),我想将该进度信息发送给客户端。但是,一旦您
    res.send(progress)
    完成了响应,就不能再发送任何内容了

    我显然需要一个不同的模式,我有一些想法:

  • 两个ajax调用,一个轮询进度,第二个获取结果
  • 一个调用,被调用5次,直到服务器端函数消失
  • 完全不同的东西(可能是长轮询、WebSocket等等)
  • 问题:

    我想知道推荐的模式是什么,以及如何在服务器端和客户端实现它。非常感谢示例代码或示例链接

    和往常一样,谢谢你抽出时间

    这里包含了我到目前为止的代码(有明显的功能遗漏)。严格来说没有必要回答这个问题,但我在这里提供它是为了提供一些上下文

    客户端

    var searchFunction = function() {
            var user = $("#searchTerm").val();
            $.getJSON("/search/" + user, function(data) {
                console.log(data);
                ko.applyBindings(new MyViewModel(data));
            });
            $("#content").hide();
            progressBar(5);
            $("#progress_bar").show();
            setTimeout(function() {
                progressBar(25);
            }, 1000);
            setTimeout(function() {
                progressBar(50);
            }, 2000);
            setTimeout(function() {
                progressBar(75);
            }, 3000);
            setTimeout(function() {
                $("#progress_bar").hide();
                $("#content").show();   
            }, 4000);
        };
    
    服务器

    var searchFunction = function(req, res) {   
        async.auto({
            f1: function(callback) {
                //things happen
                callback(err, res);
            },
            f2: function(callback) {
                //things happen
                callback(err, res);
            },
            f3: ['f2', function(callback, result) {
                //many things happen
                callback(err, res);
            }, 
            function(err) {
                //decisions are made
                callback(null, watchers);
            }]  
        }, function(err, result) {  
                //more exciting stuff happens       
                res.send(finalResults);
            }
        );
    };
    

    我的第一个想法是使用socket.io或类似的东西,服务器在每个里程碑处都会发出一个事件。客户端版本的searchFunction()只需进行AJAX调用,然后返回,套接字处理程序负责更新进度条。

    您可以使用事件流将完成百分比值推回到客户端。但它只适用于现代浏览器。我相信是IE9+。下面是一个示例事件流:

    html

    客户端(jQuery)-侦听/处理事件流

    var source = new EventSource('progress');
    source.addEventListener('progress', function(e) {
      var percentage = JSON.parse(e.data),
      //update progress bar in client
      $("#progress .bar").css({ width: percentage });
    }, false);
    
    服务器端-推送具有新进度百分比的事件

    res.writeHead(200, {'Content-Type': 'text/event-stream'});
    res.write("event: progress\n");
    //push the percentage to the client (ie: "10%")
    res.write("data: "+"10%".toString()+"\n\n");
    

    这将由您在UI中定义进度条——我将使用一个固定宽度的div和一个子项,该子项具有css规则w/基于百分比的宽度。这将得到更新。

    谢谢您的回答。我对UI表示没有问题-我们有一个很好的动画进度条。相反,我对客户机-服务器动态感兴趣——我要调用服务器多少次?这个循环是什么样子的?每次搜索我是否需要调用服务器5次(以获得中间进度)?一旦发送了更新进度条的响应,比如10%,您将如何使用相同的响应更新进度条。Bcoz如果您这样做,我会收到一个错误,说明无法将头设置为已发送的响应。你能在要点中给出完整的工作示例吗。我问了一个相关的问题,这可能比服务器发送的事件要好。
    var source = new EventSource('progress');
    source.addEventListener('progress', function(e) {
      var percentage = JSON.parse(e.data),
      //update progress bar in client
      $("#progress .bar").css({ width: percentage });
    }, false);
    
    res.writeHead(200, {'Content-Type': 'text/event-stream'});
    res.write("event: progress\n");
    //push the percentage to the client (ie: "10%")
    res.write("data: "+"10%".toString()+"\n\n");