Reputation: 9389
I currently have the following view thats is loading a bunch of images, one for each character inside an array. The problem is that get_character_thumbnail
calls an api to get the images url and thats being done synchronously when the user requests the page data.
<% @comic.characters.each do |character| %>
<div class = "col-sm-6 col-md-3">
<div class = "thumbnail">
<%= image_tag(get_character_thumbnail(character)) %>
</div>
<div class = "caption">
<p><%= character['name'] %></p>
</div>
</div>
<% end %>
I want to enforce that each call to get_character_thumbnail(character)
will be done asynchronously and the page doesn’t get stuck.
def get_character_thumbnail(character)
response = HTTParty.get(character['resourceURI'], get_basic_api_options)
response['data']['results'][0]['thumbnail']['path'] + '/portrait_large.jpg'
end
Since I’m pretty new to ruby on rails I’m struggling a little bit to setup an ajax call to do the trick. Does anyone have a suggestion or a link that could help me?
Upvotes: 3
Views: 429
Reputation: 407
You should make an AJAX call and get all the images in response. Then store in Javascript object.
Reason for the Page Freeze -
You can check my Image Preview library (https://github.com/palash-kulkarni/image_uploader/blob/master/image-uploader-1.0.0.js). Its in progress, but i know it will definitely help you.
Link to Demo (https://github.com/palash-kulkarni/image_uploader/tree/master/Demo)
$.each(files, function (_, file) {
if (image.types.test(file.type)) {
that.displayPreview(file, categoryName, image);
that.bindSingleDeleteEvent(categoryName, image);
} else {
that.clientMessage.display('#flash', image.failureMessage.invalidFileType);
}
});
// Iterate object of images
reader = new FileReader();
reader.onload = (function (img) {
return function (event) {
img.attr('src', event.target.result);
};
})(img);
reader.readAsDataURL(imageFile);
// End Iterator
Upvotes: 1
Reputation: 26778
Your routes should always return a response immediately. Here's one approach in which you're writing a custom endpoint to serve a single character image. Your html page would load quickly, then you can set the img src attributes to point at your image route.
Here's some example code to clarify:
some html.erb template
<% @comic.characters.each do |character| %>
<img src='/character_image/<%= character.id %>'>
<% end %>
a new route, get '/character_image/:id
'
def character_image
@char = Character.find(id: params[:id])
img_path = "tmp/char_img_#{@char.id}.jpg"
unless File.exists?(img_path)
img_url = get_char_img(@char) # hit your API to get the url
`wget #{img_url} -O #{img_path}`
end
send_file img_path, type: 'image/jpg', disposition: 'inline'
end
This code will cache the image to avoid duplicate API requests if, say, your html page were refreshed.
I'm using tmp/
here because it's a write-enabled location on Heroku (which blocks filesystem writes to other locations). On other environments (locally, for example), you could choose to save the images to public/
, which Rails serves statically by default.
Upvotes: 1