【问题标题】:How to edit request url in service worker?如何在服务人员中编辑请求 url?
【发布时间】:2020-04-23 06:07:37
【问题描述】:

我为我的 pwa 使用缓存优先缓存策略,对于每个 GET 请求,我首先查看该请求是否存在于缓存中,如果存在,我将其返回并更新缓存。

问题是用户可以在多个项目之间切换,所以当他们切换到另一个项目时, 当他们第一次打开某个 url 时,他们会从以前的项目中获取内容(如果它存在于缓存中)。

我的解决方案是尝试在 service worker 中添加 GET 参数 ?project=projectId(project=2 例如),这样每个项目都会有自己的请求版本保存在缓存中。 我想将项目 ID 连接到 event.request.url,但我读过 here 它是只读的。

这样做之后,希望我的缓存中有这样的网址:

代替:https://stackoverflow.com/questions

我会:https://stackoverflow.com/questions?project=1

还有:https://stackoverflow.com/questions?project=2

所以我会从我正在进行的项目中获得问题,而不是仅仅从以前的项目中获得问题,/questions 已经保存在缓存中。

有没有办法在 service worker 中编辑请求 url?

我的服务人员代码:

self.addEventListener('fetch', function(event) {
  
  const url = new URL(event.request.clone().url);
  if (event.request.clone().method === 'POST') {
      // update project id in service worker when it's changed
      if(url.pathname.indexOf('/project/') != -1 ) {
            // update user data on project switch
            let splitUrl = url.pathname.split('/');
            if (splitUrl[2] && !isNaN(splitUrl[2])) {
                console.log( user );
                setTimeout(function() {
                  fetchUserData();
                  console.log( user );
                }, 1000);
            }
       }  
       // do other unrelated stuff to post requests
       .....
  } else { // HANDLE GET REQUESTS
      // ideally,here I would be able to do something like this:
      if(user.project_id !== 'undefined') {
          event.request.url = event.request.url + '?project=' + user.project_id;
      }

      event.respondWith(async function () {
        const cache = await caches.open('CACHE_NAME')

        const cachedResponsePromise = await cache.match(event.request.clone())
        const networkResponsePromise = fetch(event.request.clone())
        if (event.request.clone().url.startsWith(self.location.origin)) {
          event.waitUntil(async function () {
            const networkResponse = await networkResponsePromise.catch(function(err) {
              console.log( 'CACHE' );
              // return caches.match(event.request);
              return caches.match(event.request).then(function(result) {
                  // If no match, result will be undefined
                  if (result) {
                       return result;
                  } else {
                       return caches.open('static_cache')
                         .then((cache) => {
                             return caches.match('/offline.html');
                       });
                  }
             });
            });
            await cache.put(event.request.clone(), networkResponse.clone())
          }())
        }
       
        // news and single photos should be network first       
        if (url.pathname.indexOf("news") > -1 || url.pathname.indexOf("/photos/") > -1) {
            return networkResponsePromise || cachedResponsePromise;  
        }
        return cachedResponsePromise || networkResponsePromise;
      }())
      
  }
});

【问题讨论】:

    标签: javascript caching request service-worker progressive-web-apps


    【解决方案1】:

    在读取/写入缓存存储 API 时,可以使用任何 URL 作为缓存键。例如,当通过put() 写入缓存时,您可以传入一个表示您希望用作第一个参数的 URL 的字符串:

    // You're currently using:
    await cache.put(event.request.clone(), networkResponse.clone())
    
    // Instead, you could use:
    await cache.put(event.request.url + '?project=' + someProjectId, networkResponse.clone())
    

    但我认为完成您所追求的更好的方法是为每个项目使用不同的缓存名称,然后在每个不同名称的缓存中,您不必担心修改缓存键以避免碰撞。

    // You're currently using:
    const cache = await caches.open('CACHE_NAME')
    
    // Instead, you could use:
    const cache = await caches.open('CACHE_NAME' + someProjectId)
    

    (我假设您有一些可靠的方法来确定服务工作者内部的正确 someProjectId 值应该是什么,具体取决于哪个客户端正在发出传入请求。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-17
      • 2019-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多