Search code examples
server-side-renderingastrojsswrajax-polling

How can I poll an ajax request in astro


Is there some way I can poll to an endpoint using astro??

I'm currently using SSR to get the data from the endpoint at page request time. But I would like to poll to that endpoint and update the astro component every few seconds. How would I achieve this??


Solution

  • Solution SSE

    you can achieve that with SSE Server Sent Event. in this example I update Astro client side from events coming from mqtt client running on the server, so that client can see updates coming without refreshing the page nor keep polling an api.

    Example

    api

    import {logger} from '@/libs/logger.js'
    import {SSE_Emitter} from '@/libs/heat_state'
    
    export async function get({request}){
    
        logger.info("heat_events> get()")
        
        const stream = new ReadableStream({
            start(controller){
                const events_listener = (devices)=>{
                    if(controller){
                        logger.verbose("heat_events> SSE_Emitter 'heat'")
                        const data = `data: ${JSON.stringify(devices)}\r\n\r\n`;
                        controller.enqueue(data)
                    }else{
                        logger.warn("heat_events> no sse_controller")
                    }
                }
                SSE_Emitter.off('heat',events_listener)
                SSE_Emitter.on('heat',events_listener)
            },
            cancel(){
                logger.info("heat_events> cancel() closing")
                if(sse_controller){
                    sse_controller.close()
                }
            }
        })
    
        return new Response(stream, {
            status: 200,
            headers: {
                'Content-Type': 'text/event-stream',
                'Connection': 'keep-alive',
                'Cache-Control': 'no-cache'          
            }
        });
    }
    

    client script

    function setup_sse(){
            const evtSource = new EventSource("/api/heat_events")
        
            evtSource.onmessage = (event) => {
                dispatch_heat_state(JSON.parse(event.data))
            }
            evtSource.onerror = (err) => {
                  console.error("EventSource failed:", err);
                  evtSource.close();
            };  
        }
        setup_sse()
    

    Reference example

    as it is more practicale to see the above code in real example, here reference in a full project with the above code