Skip to content

Instantly share code, notes, and snippets.

@rpggio
Last active June 21, 2024 09:32
Show Gist options
  • Save rpggio/5f521e1f15f969529f4fe506fc0d1c0a to your computer and use it in GitHub Desktop.
Save rpggio/5f521e1f15f969529f4fe506fc0d1c0a to your computer and use it in GitHub Desktop.
Automatic retry for iframe loading (workaround for Google Doc Viewer 204 issue)
function GoogleDocFrame({ url }: { url: string }) {
const frameRef = useRef<HTMLIFrameElement>(null)
const viewerUrl = `https://docs.google.com/viewer?embedded=true&url=${url}`
let cancel: () => void | undefined
useEffect(() => {
cancel = setFrameSrcWithRetry(frameRef.current!, viewerUrl, true)
// unmount
return () => {
if (cancel) {
cancel()
}
}
}, [url])
return <iframe ref={frameRef} />
}
/**
* Set src for an iframe. If the iframe does not load, try setting src again to
* force reload. Repeat for given number of times.
* This can be used as a workaround for Google doc viewer 204 issue: https://tinyurl.com/y7zx253q
* Viewer URL pattern: [https://docs.google.com/viewer?embedded=true&url=PUBLIC_URL]
* @param iframe
* @param src
* @param maxRetries - Max number of time to try frame reload
* @param initialDelayMs - Initial delay time to use. Exponential easing is used
* for additional cycles.
*/
export default function setFrameSrcWithRetry(
iframe: HTMLIFrameElement,
src: string,
maxRetries = 4,
initialDelayMs = 3000) {
console.log('setting frame source')
let retriesLeft = maxRetries
let loaded = false
let timeoutRef: any = null
let delayMs = initialDelayMs
const cancel = () => {
retriesLeft = 0
if (timeoutRef) {
clearTimeout(timeoutRef)
}
}
const setRetry = () => {
setTimeout(() => {
if (!loaded && retriesLeft-- > 0) {
log.info('forcing iframe refresh')
iframe.src = src
setRetry()
delayMs *= 1.5
}
}, delayMs)
}
iframe.onload = () => {
loaded = true
cancel()
}
iframe.src = src
setRetry()
return cancel
}
@opiispanen
Copy link

I actually converted this to Vue version with the help of ChatGPT and it works fine! 😃

I just wonder what is the reason of the 204 No content, it looks like if the same request is done often they just respond with 204. Is there a better way to do this in 2024, or embedding PDF in general (especially on mobile)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment