can i be notified of cookie changes in client side javascript

后端 未结 6 1151
梦毁少年i
梦毁少年i 2020-12-03 01:21

Can I somehow follow changes to cookies (for my domain) in my client side javascript. For example a function that gets called if a cookie gets changed , deleted or added

6条回答
  •  感情败类
    2020-12-03 02:03

    Method 1: Periodic Polling

    Poll document.cookie

    function listenCookieChange(callback, interval = 1000) {
      let lastCookie = document.cookie;
      setInterval(()=> {
        let cookie = document.cookie;
        if (cookie !== lastCookie) {
          try {
            callback({oldValue: lastCookie, newValue: cookie});
          } finally {
            lastCookie = cookie;
          }
        }
      }, interval);
    }
    

    Usage

    listenCookieChange(({oldValue, newValue})=> {
      console.log(`Cookie changed from "${oldValue}" to "${newValue}"`);
    }, 1000);
    
    document.cookie = 'a=1';
    

    Method 2: API Interception

    Intercept document.cookie

    (()=> {
      const channel = new BroadcastChannel('cookie-channel');
      channel.onmessage = (e)=> { // get notification from other same-origin tabs/frames
        document.dispatchEvent(new CustomEvent('cookiechange', {
          detail: e.data
        }));
      };
    
      let expando = '_cookie';
      let lastCookie = document.cookie;
      let checkCookieChange = ()=> {
        let cookie = document[expando];
        if (cookie !== lastCookie) {
          try {
            let detail = {oldValue: lastCookie, newValue: cookie};
            document.dispatchEvent(new CustomEvent('cookiechange', {
              detail: detail
            }));
            channel.postMessage(detail); // notify other same-origin tabs/frames
          } finally {
            lastCookie = cookie;
          }
        }
      };
    
      let nativeCookieDesc = Object.getOwnPropertyDescriptor(Document.prototype, 'cookie');
      Object.defineProperty(Document.prototype, expando, nativeCookieDesc);
      Object.defineProperty(Document.prototype, 'cookie', { // redefine document.cookie
        enumerable: true,
        configurable: true,
        get() {
          return this[expando];
        },
        set(value) {
          this[expando] = value;
          checkCookieChange();
        }
      });
    })();
    

    Usage

    document.addEventListener('cookiechange', ({detail: {oldValue, newValue}})=> {
      console.log(`Cookie changed from "${oldValue}" to "${newValue}"`);
    });
    
    document.cookie = 'a=1';
    

    Conclusion

    | Metric \ Method  | Periodic Polling            | API Interception |
    | ---------------- | --------------------------- | ---------------- |
    | delay            | depends on polling interval | instant          |
    | scope            | same-domain                 | same-origin      |
    

提交回复
热议问题