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

在Workbox precacheAndRoute中用异步回调确定缓存资源时遇报错如何解决?

问题:Workbox precacheAndRoute 缓存IndexedDB文件路径报错 additionalURLs is not iterable

我在Service Worker中使用workbox-precaching的precacheAndRoute方法,希望缓存IndexedDB中已存在的、因用户而异的文件路径,代码如下:

import { precacheAndRoute } from 'workbox-precaching';
import localforage from "localforage";

let formID;

const cachedFilesStore = localforage.createInstance({
    name: 'page-id',
    storeName: 'store'
})

const produceValuesFromCache = () => {
    return cachedFilesStore.getItem('1')
        .then(async (value) => {
            formID = formID || value.form_id;
            const cachedFiles = await cachedFilesStore.getItem(`${formID}`)
            return [
                ...cachedFiles.manifest,
                `/form/${formID}`
            ]
        });
}

precacheAndRoute([], {
    urlManipulation: async ({ url }) => {
        const files = await produceValuesFromCache();
        return files
    }
})

执行后未达到预期效果,反而出现报错:Uncaught TypeError: additionalURLs is not iterable。另外,将文件存入IndexedDB的代码位于路由form/${formID}下的index.html文件中。


错误原因及解决方法

核心错误点

  1. 误用urlManipulation回调:这个回调的作用是处理请求时的URL重定向逻辑(比如将旧路径映射到新路径),不是用来动态添加预缓存项的。预缓存是在Service Worker的install阶段执行的,你在请求阶段才去IndexedDB获取数据,时机完全不对。
  2. 返回格式不符合要求:urlManipulation要求返回Array<Array<URL>>类型(外层数组是重定向选项组,内层数组是具体的URL对象数组),你直接返回了字符串路径数组,Workbox尝试遍历每个字符串时触发了“不可迭代”的错误。

正确实现思路

要动态预缓存IndexedDB中的文件,需要在Service Worker的install事件中完成以下步骤:

  • 从IndexedDB读取目标文件路径
  • 整理成Workbox预缓存接受的格式
  • 调用precacheAndRoute执行预缓存

修正后的代码

import { precacheAndRoute } from 'workbox-precaching';
import localforage from "localforage";

const cachedFilesStore = localforage.createInstance({
    name: 'page-id',
    storeName: 'store'
});

// 在install事件中完成动态预缓存
self.addEventListener('install', async (event) => {
    try {
        // 从IndexedDB获取formID
        const idData = await cachedFilesStore.getItem('1');
        if (!idData?.form_id) {
            console.log('未找到formID,跳过动态预缓存');
            return;
        }
        const formID = idData.form_id;
        
        // 获取需要缓存的文件清单
        const cachedFiles = await cachedFilesStore.getItem(`${formID}`);
        if (!cachedFiles?.manifest) {
            console.log('未找到缓存文件清单');
            return;
        }
        
        // 整理预缓存项:转为Workbox接受的格式,支持字符串或{url: string}对象
        const precacheList = [
            ...cachedFiles.manifest,
            `/form/${formID}`
        ];
        
        // 执行预缓存
        precacheAndRoute(precacheList);
        
        // 强制等待安装完成后激活新的Service Worker(可选)
        self.skipWaiting();
    } catch (error) {
        console.error('动态预缓存失败:', error);
    }
});

// 如果有静态预缓存清单(比如通过workbox-build生成的),可以合并进来
// precacheAndRoute(self.__WB_MANIFEST);

额外注意事项

  • 当IndexedDB中的缓存路径更新时,需要触发Service Worker更新(比如修改Service Worker文件内容、添加版本注释),否则旧的预缓存清单不会自动更新。
  • 激活新Service Worker后,可以调用self.clients.claim()让所有已打开的页面立即使用新的Service Worker(可选,需在activate事件中添加)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 15:15:34