2017-07-07 14 views
0

我有一个基本的表单,当提交时,触发一个创建请求到外部API。在提交时,会出现一个包含进度条的阶段值,而不是提交按钮。创建过程需要花费时间在外部API上,因此我必须每秒使用while status == 'inactive'运行一些Show请求,并在显示请求响应为status: 'active'时停止。 每个Show请求响应还包含一个'stage'属性,该属性显示创建过程的阶段(连接,创建,获取,整理等)。对于每个请求,当前阶段都存储在@stage变量中,可以使用ApiRequest.stage访问该变量。每个API相关的东西都在一个服务文件中。Rails - 用动态变量修改%p的文本

我的CoffeeScript与舞台+进度条更改提交按钮:

$('#new_connection').on 'submit', -> 
    button = $('#submit_button') 
    progress = $('.loading') 
    button.fadeOut 500 
    setTimeout (-> 
     if button.is(':hidden') 
     progress.fadeIn 500 
     return 
    ), 509 
    return 

和部分舞台+进度条:

.loading 
    %p.center-align#stage <!-- This should display the stage in real time --> 
    .progress <!-- This is a materializecss progress bar --> 
    .indeterminate 

如何更新内部#stage文字与ApiRequest.status每次实时在同一页面上更改值时,从表单提交到结束的那一刻(当所有背景中的所有内容都完成后,它将重定向到create.html)?

回答

0

好的,你所要做的就是在控制器中创建一个读取变量的方法:​​3210。
format.json { render json: { stage: @stage } }写一个respond_to do |format|
现在您必须为此自定义控制器方法创建路线:get '/your/link', to: 'controller#custom_method', as: 'stage'
所有剩下的就是通过Ajax来触发这个方法:

$.get({ 
    url: "your/link.json", 
    success: function(data) { 
    $('#your_paragraph_id').text(data['stage]); 
    }, 
}); 

你可以把这个Ajax调用的setInterval函数。

1

实时显示您操作的状态,或者至少接近实时,你必须要么

  • 调查定期服务器,看看状态已经改变 - 那就是,保持每秒钟或两次触发show端点,并更新成功回调中的状态标签
  • 或者您可以实现一种方案,只要状态使用WebSocket,长轮询或其他技术进行更改,服务器就会通知该页面。

投票就像当你驾驶一辆汽车时,你的一位乘客不停地问:“我们到了吗?每一秒。它不是非常有效,特别是在操作需要很长时间的情况下,因为每隔012秒发出一个单独的HTTP请求,只能返回一个“仍在进行中”的响应。但它很容易实现,所以如果show操作很快并且操作本身很快完成,那么它可能是一个很好的折衷方案。

另一种方法是让服务器在状态更改发生时通知您。为此,您需要有一个发布者订户基础架构。如果您使用的是Rails 5,那么Action Cable可能是您最好的选择,因为它内置于Rails中。您可以在此处找到不同可用技术的详细比较:In what situations would AJAX long/short polling be preferred over HTML5 WebSockets?

如果您正在使用轮询,则可以将常规AJAX调用的success回调中的状态标签更新为show。如果show只呈现HTML,那么你将不得不从AJAX响应数据解析出新的状态:在普通的JavaScript

<!-- example output of show.html.erb --> 
<!-- ... --> 
    <div id="current-status"><%= @status %></div> 
<!-- ... --> 

例在AJAX响应解析页面并获取#current-status<div>的价值:

setTimeout(function() { 
    $.get({ 
    url: "<%= show_page_path %>", 

    success: function(data) { 
     var response = $("<div></div>"). 
     append($.parseHTML(data, null, true)); 

     $("#current-status").html(
     $("#current-status", response) 
    ); 
    }, 
    }); 
}, 1000); 

当然,如果你添加一个JSON终点为show动作只包括状态:

# in the controller 
respond_to do |format| 
    format.html 
    format.json do 
    render json: { status: @status } 
    end 
end 

然后,你不必做任何HTML解析:

setTimeout(function() { 
    $.get({ 
    url: "<%= show_page_path(format: :json) %>", 

    success: function(data) { 
     $("#current-status").text(data.status); 
    }, 
    }); 
}, 1000); 

的例子是未经检验的,所以他们可能没有一些修改很好地工作。

+0

在后端一切正常,我不得不每秒都会触发'show'动作,因为每个请求都会返回一个新的'stage'进程。虽然所有内容都在后台运行,但用户可通过进程栏获取进程栏(连接,创建,获取,整理)。随着每一个新的请求,我更新'@舞台'。我想在视图中显示“@ stage”,这样用户就可以知道当时正在发生的事情。这是个问题,'@ stage'不是固定的,它每改变一次'show'请求都会改变它的值,那么我怎样才能用更新后的'@ stage'无刷新更新视图呢? – YoloSnake

+0

AJAX请求完全在后台运行,默认情况下它们不会更新当前显示的页面。如果你的'show'动作返回HTML,你将不得不使用JavaScript自己解析出响应的新状态,并手动更新当前页面上的标签。 –

+0

我唯一的想法是在setInterval函数中触发一个Ajax请求,刷新'@ stage'。不知道如何实现它。 – YoloSnake