Search code examples
webservice-workerworkboxbackground-sync

Duplicate post request sent by Service Worker


I just found this issue because I was trying to solve the duplicate post request issue when I am using workbox-background-sync. There is a function of my web app to upload the photos. But every time I did uploaded twice to the database. Here is the code I have:

const bgSyncQueue = new workbox.backgroundSync.Queue(
        'photoSubmissions',
        {
            maxRetentionTime: 48 * 60,//48 hours
            callbacks: {
                queueDidReplay: function (requests) {
                    if (requests.length === 0) {
                        removeAllPhotoSubmissions();
                    }
                    else {
                        for(let request of requests) {
                            if (request.error === undefined && (request.response && request.response.status === 200)) {
                                removePhotoSubmission();
                            }
                        }
                    }
                }
            }
        });
    workbox.routing.registerRoute(
        new RegExp('.*\/Home\/Submit'),
        args => {
            const promiseChain = fetch(args.event.request.clone())
            .catch(err => {
                bgSyncQueue.addRequest(args.event.request);
                addPhotoSubmission();
                changePhoto();
            });
            event.waitUntil(promiseChain);
        },
        'POST'
    );

It may because the fetch(args.event.request.clone()). If I remove it, then there is no duplication anymore. I am using workbox 3.6.1 .


Solution

  • Finally I found the solution. Below is my code:

    const photoQueue = new workbox.backgroundSync.Plugin('photoSubmissions', {
        maxRetentionTime: 48 * 60, // Retry for max of 48 Hours
        callbacks: {
            queueDidReplay: function (requests) {
                if (requests.length === 0) {
                    removeAllPhotoSubmissions();
                }
                else {
                    for(let request of requests) {
                        if (request.error === undefined && (request.response && request.response.status === 200)) {
                            removePhotoSubmission();
                        }
                    }
                }
            }
        }
    });
    
    const myPhotoPlugin = {
        fetchDidFail: async ({originalRequest, request, error, event}) => {
                        addPhotoSubmission();
                        changePhoto();
        }
    };
    
    workbox.routing.registerRoute(
        new RegExp('.*\/Home\/Submit'),
        workbox.strategies.networkOnly({
            plugins: [
                photoQueue,
                myPhotoPlugin
            ]
        }),
        'POST'
    );
    

    I removed fetch. If we still want to controll by ourselves, we need to use respondWith(). I have tested it, it is working. But I would like to use more workbox way to solve the problem. I am using workbox 3.6.3 and I created my own plugin to include a callback function fetchDidFail to update my views. Here are the references I found: one and two. There are no duplicate posts anymore.