You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PWA中联网(开启WiFi)时Background Sync代码无法自动执行问题

Troubleshooting Your PWA Background Sync Issue with Firebase

Hey there, let's break down why your Background Sync isn't triggering automatically when you go online, and fix it step by step.

First, the Core Problem in Your Code

Looking at your service worker code, the biggest issue is that you're not properly waiting for all your fetch requests to finish before the service worker exits. When you loop through your IndexedDB data and fire off fetch calls, those are asynchronous operations—but your current code doesn't tell event.waitUntil() to wait for all of them to complete. The service worker might terminate before the sync finishes, leaving your data stuck in IndexedDB.

Fix 1: Properly Wait for All Sync Operations

Rewrite your sync handler to collect all fetch promises and wait for them to resolve with Promise.all(). Here's the adjusted code:

self.addEventListener('sync', function(event) {
  console.log('Background syncing...', event);
  if (event.tag === 'sync-new-posts') {
    console.log('Syncing new Posts...');
    event.waitUntil(
      readAllData('sync-posts')
        .then(function(data) {
          // Collect all sync promises to wait on
          const syncPromises = [];
          
          for (const dt of data) {
            const postPromise = fetch('xxx some firebase post url xxx', {
              method: 'POST',
              headers: {
                'Content-Type': 'application/json',
                'Accept': 'application/json'
              },
              body: JSON.stringify({
                id: dt.id,
                title: dt.title,
                content: dt.content
              })
            })
            .then(function(res) {
              console.log('Sent data', res);
              if (res.ok) {
                // Delete the item using the original dt.id (more reliable than resData.id)
                return deleteItemFromData('sync-posts', dt.id);
              }
              throw new Error('Failed to sync post to Firebase');
            })
            .catch(function(err) {
              console.log('Error while sending data', err);
              throw err; // Ensure the promise fails so we know sync didn't work
            });
            
            syncPromises.push(postPromise);
          }
          
          // Wait for all posts to sync before finishing
          return Promise.all(syncPromises);
        })
        .catch(err => console.error('Full sync failed:', err))
    );
  }
});

Fix 2: Double-Check Sync Registration

Make sure you're registering the sync event every time you save data to IndexedDB while offline. If you don't trigger the registration, the browser won't know it needs to sync later. Add this code wherever you save posts to sync-posts in IndexedDB:

// After saving data to IndexedDB
navigator.serviceWorker.ready.then(swReg => {
  return swReg.sync.register('sync-new-posts');
}).catch(err => console.error('Failed to register sync event:', err));

Repeating this registration is safe—browsers will ignore duplicate registrations for the same tag.

Fix 3: Fix Firebase ID Matching

Firebase's default POST endpoint generates a new unique ID for each post, which means resData.id won't match the dt.id you sent. This causes deleteItemFromData to fail, leaving old posts in IndexedDB to be retried forever.

You have two options here:

  1. Use PUT instead of POST to save the post under your existing dt.id:
    fetch(`xxx some firebase post url xxx/${dt.id}`, {
      method: 'PUT',
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
      },
      body: JSON.stringify({
        title: dt.title,
        content: dt.content
      })
    })
    
  2. Delete using the original dt.id (like we did in the first fix) since you already know which entry to remove from IndexedDB.

How to Test Properly

To confirm your sync works:

  1. Save a post while offline.
  2. Close your tab (or put the app in the background)—Background Sync often triggers when the app isn't active.
  3. Turn on WiFi.
  4. Check Chrome DevTools > Application > Background Sync to see if the sync event fires, and watch the console for logs.

内容的提问来源于stack exchange,提问作者Robin Rai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:23:40