如何在加载视图时处理长api请求

时间:2017-01-04 20:47:57

标签: javascript ruby-on-rails api

我正在使用显示用户内容的rails应用。在我的一个控制器#show动作中,我做了一个api调用来为" up next"内容。这个api调用大约需要5秒才能响应,而不是非常长,但是在加载页面之前让用户等待的时间太长了。

在用户向下滚动页面的2/3处之前,推荐本身不会显示,因此在最初加载页面时他们不需要在那里。

我的问题是,是否有一种很好的方法来加载其余页面内容并等待加载页面的那一部分,直到api调用完成并且建议准备就绪?提前谢谢!

控制器

class DiscoverEmailsController < ApplicationController
  def show
    @discover_email = DiscoverEmail.find_by(message_id: params[:message_id])

    #just in development for now
    @up_next = Rails.env.development?
        #API call that takes too long to wait for
        up_next_ids = RecommendationsHelper.get_one_step_recommendations(@discover_email.subject, @discover_email.preview, @discover_email.senders_name)

        up_next_ids.each do |message_id_and_score|
            break if @up_next.length >= 4

            discover_email = DiscoverEmail.find_by(message_id: message_id_and_score[1])

            unless discover_email.nil?
                @up_next << discover_email unless discover_email.image_url.nil? || discover_email.senders_name.nil? || discover_email.subject.nil?
            end
        end
    else
        @up_next = DiscoverEmail.where.not(senders_name: nil, image_url: nil, subject: nil).order(date: :desc).last(4)
    end

    DiscoverEmail.track_view(email_address, @discover_email)
  end
end

查看正文

  <body class="iframe-page">

<h3 class="email-subject"><%= @discover_email.subject %></h3>

<div class="iframe-content">
  <iframe id="iframe" sandbox="allow-same-origin allow-scripts allow-popups" src="<%= @url %>" allowfullscreen></iframe>


     #Section I'd like to wait to load since it's hidden until users are most of the way down the page 
  <div id="discover-up-next">
    <div id="up-next-border">
      <div class="border-lines"></div>
      <p id="up-next-text">NEXT UP</p>
      <div class="border-lines"></div>
    </div>

    <div id="up-next-cells" style="display: inline-flex; height: 110px;">
      <% @up_next.each_with_index do |discover_email, index| %>
        <% if discover_email.subscription.clearbit_logo_url.nil? || discover_email.subscription.clearbit_logo_url == "noclearbitlogo" %>
        <%      logo_safe = "https://s3-us-west-2.amazonaws.com/myblendappimages/blend_logo_mashup_pattern_80.png" %>
        <% elsif discover_email.subscription.clearbit_logo_url.include? "http://logo.clearbit.com/"%>
        <%      logo_safe = discover_email.subscription.clearbit_logo_url %>
        <% else %>
        <%      logo_safe = "http://logo.clearbit.com/" + discover_email.subscription.clearbit_logo_url %>
        <% end %>

        <% subject = discover_email.fit_subject %>

        <div id="recommendation-<%= index + 1 %>" style="height: 110px; width: 320px;">
          <% unless index == 0 %>
          <div class="left-line" >
          <% end %>
          <div class="up-next-cell">
            <div class="row">
              <div class="discover-up-next-cell-text col-xs-8" style="padding: 0 0 0 10px; text-align: left;">
                <%= link_to subject, discover_show_path(message_id: discover_email.message_id), class: "up-next-cell-subject" %>
                <div class="row" style="margin-top: 5px;">
                  <div class="gallery_card_logo col-sm-2 col-xs-3 no-padding" style="width: 20px !important; margin-right: 5px;">
                    <%= image_tag(logo_safe, style: "width: 20px; height: 20px; float: left;") %>
                  </div>
                  <div class="col-xs-9 no-padding">
                    <p class="discover-up-next-senders-name"><%= discover_email.senders_name %></p>
                  </div>
                </div>
              </div>

              <div class="col-xs-4 no-padding">
                <%= link_to(image_tag(discover_email.image_url, class: "discover-email-up-next-cell-image"), discover_show_path(message_id: discover_email.message_id)) %>
              </div>
            </div>
          </div>
          <% unless index == 0 %>
          </div>
          <% end %>
        </div>
      <% end %>
    </div>
  </div>
 </div>
</body>

1 个答案:

答案 0 :(得分:0)

使用javascript / ajax和ruby的组合解决了这个问题。

AJAX

<script type="text/javascript">
  #use ajax to call controller action AFTER page finishes loading
  $(window).load(function(){
    $.ajax({
      url: "/discover/up_next",
      cache: false,
      data: {"random": "data"},
      success: function(html){
        $("#discover-up-next-container").append(html);
      }
    });
  });
</script>

由ajax

调用的ruby控制器动作
def up_next
  wait = Wait.new
  @up_next = #get up next content

  #wait until content is ready to load html
  wait.until { @up_next.empty? == false }
  render layout: false
end