import { CancelFunction , Result , ResultCallback , Suspender } from "./Types" ; param { Suspender < T > } suspender return { Suspender < T > } export const async = < T > ( suspender ) : Suspender < T > => { let result ; let resultCallback ; return ( resCallback ) => { if ( result !== undefined ) { resCallback ( result ) ; } else { resultCallback = resCallback ; } return suspender ( ( res ) => { if ( resultCallback !== undefined ) { resultCallback ( res ) ; } else { result = res ; } } ) ; } ; } ; params return { Suspender < T > } export const race = < T > ( ... suspenders ) : Suspender < T > => { return ( resultCallback ) => { const cancelCallbacks = [ ] ; for ( let [ index , suspender ] of suspenders . entries ( ) ) { cancelCallbacks . push ( suspender ( ( value ) => { cancelCallbacks [ index ] = null ; for ( let m = 0 ; m < suspenders . length ; m ++ ) { const cancel = cancelCallbacks [ m ] ; if ( cancel ) { cancel ( ) ; } else { cancelCallbacks [ m ] = null ; } } resultCallback ( value ) ; } ) ) ; } return ( ) => { for ( const cancelCallback of cancelCallbacks ) { if ( cancelCallback ) { cancelCallback ( ) ; } } } ; } ; } ; param { number } millis return { Suspender < void > } export const wait = ( millis ) : Suspender < void > => { return ( resultCallback ) => { const timeout = setTimeout ( ( ) => { resultCallback ( { value : undefined } ) ; } , millis ) ; return ( ) => { clearTimeout ( timeout ) ; } ; } ; } ; export const awaitCancellation = ( ) : Suspender < void > => { return ( ) => { } ; } ; param { Promise < T > } promise return { Suspender < T > } export const promiseSuspender = < T > ( promise ) : Suspender < T > => { return ( resultCallback ) => { promise . then ( ( value ) => { resultCallback ( { value } ) ; } , ( error ) => { resultCallback ( { tag : `error` , error } ) ; } ) ; } ; } ; param { string } url return { Suspender < T > } export const httpGet = ( url ) : Suspender < string > => { return ( resultCallback ) => { const xhttp = new XMLHttpRequest ( ) ; xhttp . onloadend = function ( ) { if ( this . status === 200 ) { resultCallback ( { value : this . responseText } ) ; } else { resultCallback ( { tag : `error` , error : new Error ( `code: ${ this . status } text: ${ this . statusText }` ) } ) ; } } ; xhttp . open ( `GET` , url , true ) ; xhttp . send ( ) ; return ( ) => { xhttp . abort ( ) ; } ; } ; } ;