I've written goroutines that make API calls to Dropbox to get temporary image links to display on a personal website via golang templates. Dropbox is a little funny in that I must first make a request to get all images in the desired Dropbox folder and their specific paths. I then must make another call to Dropbox with the specific paths in the request body and Dropbox will respond with a temporary link to use.
So I have one go routine that that gets the list of image paths and sends them to another go routine via a channel. That second go routine then makes the request and gets the temporary link from DB which is then sent across another channel to a http handler func. Being that there could possibly be several hundreds of pictures, this process takes some time and the browser sits idle while the backend is making http requests. I would like to display a loading screen while golang is making all the http requests
I should note that the webpage itself is taking the images and making an automatic slideshow with them. I'm passing the links into the html using templates and "range" over them.
{{range .}}
<img class="mySlides w3-animate-fading" src="{{.}}" style="width:100%">
{{end}}
First I attempted to just pass the final channel of links in the template and execute it that way, but the page would never render. It just sat there waiting to load.
err := templates.ExecuteTemplate(w, "index.html", LinkChannel)
The functionality that I did get to work is the following:
func homePage(w http.ResponseWriter, r *http.Request) {
var links []string
l := <-numOfImages
//Iterate over the channel and append temporary links to list
for link := range LinkChannel {
links = append(links, link.Link)
//Check if all images have been appended to break from loop
if int64(len(links)) == l {
break
}
}
//Create a struct with the links to pass to html templates
data := struct {
Images []string
}{Images: links}
//Execute template with links
err = templates.ExecuteTemplate(w, "index.html", data)
check(err)
}
where l is the total number of images initially found by the first goroutine call to Dropbox. As you can see, I'm looping through the channel and waiting for all the links before serving index.html. As stated earlier since this looping can take time, the browser sits idle. I've tried adding another template execute statement before the loop
func homePage(w http.ResponseWriter, r *http.Request) {
var links []string
l := <-numOfImages
err := templates.ExecuteTemplate(w, "load.html", nil)
//Iterate over the channel and append temporary links to list
for link := range LinkChannel {
links = append(links, link.Link)
//Check if all images have been appended to break from loop
if int64(len(links)) == l {
break
}
}
//Create a struct with the links to pass to html templates
data := struct {
Images []string
}{Images: links}
//Execute template with links
err = templates.ExecuteTemplate(w, "index.html", data)
check(err)
}
But all this did was render a nasty frankenstein of the two html pages mixed together, and I still had to wait for the Dropbox calls before anything rendered. Is there a way to show a loading screen while waiting for the go routines? Or even better, can someone hopefully point me in the right direction of my first attempt, just passing in the channel to the template and iterating over it via templates so no loading screen is needed?