import * as React from "react" ; interface Resource < Payload > { read : ( ) => Payload ; } type status = "pending" | "success" | "error" ; function createResource < Payload > ( asyncFn ) { let status = "pending" ; let result ; const promise = asyncFn ( ) . then ( ( r ) => { status = "success" ; result = r ; } , ( e ) => { status = "error" ; result = e ; } ) ; return { read ( ) { switch ( status ) { case "pending" : throw promise ; case "error" : throw result ; case "success" : return result ; } } , } ; } const cache = new Map < string , any > ( ) ; function loadImage ( source ) { let resource = cache . get ( source ) ; if ( resource ) return resource ; resource = createResource < string > ( ( ) => new Promise ( ( resolve , reject ) => { const img = new window . Image ( ) ; img . src = source ; img . addEventListener ( "load" , ( ) => resolve ( source ) ) ; img . addEventListener ( "error" , ( ) => reject ( new Error ( `Failed to load image ${ source }` ) ) ) ; } ) ) ; cache . set ( source , resource ) ; return resource ; } export default function SuspenseImage ( props ) { if ( props . src != null ) { loadImage ( props . src ) . read ( ) ; } return < img { ... props } / > ; }