【问题标题】:Update pattern for progress bar on a long ajax query长 ajax 查询进度条的更新模式
【发布时间】:2012-09-27 04:30:48
【问题描述】:

这是我所拥有的:

  1. 一个执行长时间(2-10 秒)计算(db + 外部 API 调用)的 Node.js 函数。我使用 async.auto() 来组织调用的依赖项
  2. HTML 视图页面上一个漂亮的视觉进度条
  3. 调用查询的 getJSON 函数(参见下面的代码)

现在,我只是在更新计时器上的进度条。但我希望它更准确。我已经将服务器端功能分解为 5 个里程碑(即在每个外部调用成功完成之后),我想将该进度信息发送给客户端。但是,一旦您res.send(progress) 您完成了回复,就无法再发送任何内容了。

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

  1. 2 次 ajax 调用,一次轮询进度,第二次获取结果
  2. 一个调用被调用 5 次,直到服务器端函数消失
  3. 完全不同的东西(可能是长轮询、websockets,?)

问题:

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

一如既往,感谢您的宝贵时间!

这里包含的是我到目前为止的代码(有明显的功能遗漏)。回答这个问题并不是绝对必要的,但我在这里提供它是为了提供一些背景信息。

客户

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

【问题讨论】:

    标签: jquery ajax node.js progress-bar


    【解决方案1】:

    您可以使用事件流将完成百分比值推送回客户端。但它只适用于现代浏览器。 IE9+ 我相信。这是一个示例事件流:https://github.com/chovy/nodejs-stream

    html

    <div id="progress"><span class="bar"></span></div>
    

    css

    #progress { width: 200px; background: #eee; border: 1px solid #ccc; height: 20px; }
    #progress .bar { display: inline-block; background: #ddd; width: 0; }
    

    客户端 (jQuery) - 监听 /progress 事件流

    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 如果您这样做,我会收到一条错误消息,指出无法将标头设置为已发送的响应。你能在要点中给出完整的工作示例吗?我在stackoverflow.com/q/17882285/226906 中提出了相关问题
    【解决方案2】:

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

    【讨论】:

    • 这可能比服务器发送事件更好。
    猜你喜欢
    • 1970-01-01
    • 2020-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多