Strategies for managing extended API requests during view loading

Hello, I am currently working on a Rails application focused on displaying user-generated content. Within one of my controllers, specifically the #show action, I am making an API call to generate recommendations for "up next" content. This API call typically takes around 5 seconds to return a response, which is not excessively long but still poses an issue in terms of user experience as waiting for this could delay the initial page load significantly.

The actual recommendations are intended to be visible only when users have already scrolled approximately two-thirds of the way down the page. Thus, there is no need for them to be present during the initial loading of the page.

I was wondering if there is an effective method to load the remaining content of the page first and then selectively load just the section containing the recommendations once the API call has finished fetching the necessary data. Thank you in advance!

Controller

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

    # Just in development phase
    @up_next = Rails.env.development?
        # The API call that is causing delays
        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

View Body

  <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 intended to be loaded later -->
  <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>

Answer №1

My problem was fixed using a combination of javascript/ajax and ruby.

Ajax

<script type="text/javascript>
  #utilizing ajax to invoke controller action once the page has loaded
  $(window).load(function(){
    $.ajax({
      url: "/discover/up_next",
      cache: false,
      data: {"random": "data"},
      success: function(html){
        $("#discover-up-next-container").append(html);
      }
    });
  });
</script>

Ruby Controller Action Triggered by Ajax

def up_next
  wait = Wait.new
  @up_next = #retrieve upcoming content

  #waiting for the content to be ready before loading HTML
  wait.until { @up_next.empty? == false }
  render layout: false
end

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Creating a JSON API with Express Framework

I'm looking to create a JSON API. One issue I'm facing is the need to query for both an ID and a string at different times. One approach could be to include a querystring in the URL, like so: example.com/user/RandomName example.com/user/123455 ...

Using AND and OR operators, regular expressions, and the length of a value

I'm currently working on a feature that restricts users from entering non-numeric characters and limits the input value length to no more than 6. Right now, it successfully blocks any input with more than 6 characters or containing alphabetic characte ...

Error: JSONP Label Validation Failed

My JSON URL is: The above URL returns the following JSON: { token: "2cd3e37b-5d61-4070-96d5-3dfce0d0acd9%a00a5e34-b017-4899-8171-299781c48c72" } Edit: Changed it to {"token": "2cd3e37b-5d61-4070-96d5-3dfce0d0acd9%a00a5e34-b017-4899-8171-299781c48c72"} ...

Guide to inserting an HTML file into an article's content

After downloading an extension from freefrontedit and uploading it to my server in the directory /accordeon, I successfully accessed it by pointing my browser to . However, I am now faced with the challenge of loading the index.html into my Joomla article ...

Tips on passing string without double quotes within a MongoDB query

When trying to pass a string to my mongodb query, I encountered an issue where double quotes were added to the string once inside the query. The criteria is being passed as a string because it is dynamically formed that way: str1={AccId:8,WSId:24237,Case ...

Tips for creating a custom notification container using CSS

I have been tasked with creating a notification display for a web application. The notifications should appear in the bottom right corner of the window and disappear after a certain period. Alternatively, users can click on a notification to dismiss it. Wh ...

Using JavaScript to post data to a PHP script, then triggering the execution of another

My website has two distinct pages with different purposes. On one page, there is a button that, when clicked, sends data to finalizecontract.php. The other page, contract.php, creates a TCPDF form populated with the database information and saves the resu ...

Is it possible to alter the background color once the content of an input field has been modified?

I am working with an angular reactive form and I want to dynamically change the background color of all input fields when their value is changed. Some of these input fields are pre-populated and not required. I came across a potential solution on Stack Ove ...

Exploring ways to track file upload progress with the Fetch API in ReactJS or NextJS

Currently, I am utilizing Nextjs for constructing a full-stack application. Specifically, I am focusing on the admin CMS part and attempting to implement file uploads such as images. Referring to this modified version of the code from this post. The upload ...

How can I bind an event for changing innerHTML in Angular 2?

Is there a way to implement something similar to this: <div [innerHTML]="content" (innerHTMLchange)="contentInit()"></div> Currently, I have a variable content that is updated by a service fetching a string from my express server. The content ...

Exploring Vue's feature of passing props and emitting events within nested components

Within my coding project, I am facing the challenge of properly implementing a parent component containing a form that includes a birthday component. This birthday component consists of two separate components within it. My task is to effectively pass prop ...

Place an image in the middle of a div with text aligned to the right side

How do I center an image within a div that has text on the right side? The page layout is based on percentages and I want the image to be perfectly centered with the text floated to the right. This is what I currently have: IMG.logo { display: block ...

Is it possible to iterate through various values using the same variable name in Mustache.js?

I have data structured in the following way: hello this is {{replacement_data}} and this {{replacement_data}} is {{replacement_data}}. I'm interested in using Mustache to substitute these placeholders with values from an array: [val1, val2, val3. ...

Refine the inventory by using data-price attributes to narrow down the product selection

While I have successfully implemented the filtering of the product list based on store and brand in my code, I am facing challenges in filtering it with price range. <div id="prod"> <div class="content" data-brand="Andrew" data-price="1000" d ...

How can you retrieve the current user in express.js when incorporating socket.io?

I have a web app using the express framework and socket.io for real-time chat. I am trying to get the current user's username and create a room with them in it, but I am struggling to retrieve the user info when socket.on('connection') is ca ...

D3-cloud creates a beautiful mesh of overlapping words

I am encountering an issue while trying to create a keyword cloud using d3 and d3-cloud. The problem I am facing is that the words in the cloud are overlapping, and I cannot figure out the exact reason behind it. I suspect it might be related to the fontSi ...

Creating a dynamic template in AngularJS directive

I am curious about how to create a dynamic template directive. Here's the challenge - when I am on the main page or main categories such as page1 or page2, my template should include all the divs. However, when I am on a submenu like subpage1 or subp ...

Transforming NodeJS Express HTTP responses into strings for AngularJS consumption

I have been working on creating an AngularJS program that communicates with an Express/Node.js API and a MySQL database. On the login page, I am successfully able to call the API which connects to MySQL. Depending on the correct combination of username an ...

Accessing Google authentication: A guide to programmatically prompting user consent and retrieving the CredentialResponse after successful login

Is there a way to trigger the Prompt for User Consent to open when clicking a custom HTML button instead of the Login iframe button rendered by Google? I am utilizing the Sign In With Google JavaScript API, and while I couldn't find a function to achi ...

Encountering Issue: Trying to modify the getter of an immutable property in React Native

I encountered an error while working on my react-native project The error message reads: Attempting to change the getter of an unconfigurable property import * as React from 'react'; import { Text, View, StyleSheet } from 'react-native&ap ...