Skip to content
Advertisement

Sending POST request with Fetch after closing the browser with ‘beforeunload’ / ‘unload’ eventlistener is not working

for the life of me I can’t figure out what is happening. I’ve been spending all day searching for the answer but can’t find it anywhere. I’m practicing with writing a function that emails an abandoned form to me.

This is the index.js file I run for the local host that hosts the form

const inputSelector = document.getElementById("name");
const fieldSelector = document.querySelectorAll('.formfield');
let formData = {};


fieldSelector.forEach(field =>{

    field.addEventListener('input', (e) =>{

        let formField = e.target.id;
        formData[formField] = field.value;
        
    });
})


window.addEventListener('beforeunload', () =>{
    fetch('http://localhost:8080/', {
        method:'post',
        headers:{
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({
            message: formData
        })
    })
})

The function that the request is send to, is a cloud function that contains this code:

exports.testFetch = async (req, res) =>{
    console.log(req.method);
    if(req.method === 'OPTIONS'){
        console.log('method is option')
        res.set('Access-Control-Allow-Origin', "*")
        res.set('Access-Control-Allow-Methods', 'GET, POST');
        res.set('Access-Control-Allow-Headers', 'Content-Type');
    }

    else{
   
        console.log('full body: ', req.body);
        console.log('message: ', req.body.message);
    }

    res.send('response')

}

Now whenever I fill out the form fields and then browse from that page to another page it works perfectly, the cloud function console.logs the form fields. However when I just CLOSE the page by clicking X the cloud function only console.log ‘OPTIONS’ and ‘method is option’. It looks like it only sends the options part of the post request. I’ve been spending all afternoon looking for a solution but I can’t find it anywhere. Super frustrating. When I just add the fetch function to a button and then press the button it works perfectly aswell. It’s just with closing the browser that it doesn’t seem to work and gets stuck in OPTIONS. If you have any tips, please let me know!

Advertisement

Answer

As Endless’s answer discusses, sendBeacon is an option. But the problem is your fetch request is not using the keepalive flag.

Normally, when a document is unloaded, all associated network requests are aborted. But the keepalive option tells the browser to perform the request in the background, even after it leaves the page. So this option is essential for our request to succeed.

window.addEventListener('beforeunload', () => {
        fetch('http://localhost:8080/', {
            method:'post',
            headers:{
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                message: formData
            }),
            keepalive: true // this is important!
        })
    })
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement