我可以在客户端javascript中以某种方式跟踪Cookie(对于我的域)的更改。例如,如果cookie被更改,删除或添加,则会调用一个函数
按优先顺序
为什么呢?因为我在窗口/标签#1中依赖的cookie可以在窗口/标签#2中更改。
我发现chrome允许扩展程序通知Cookie更改。但那是我最不喜欢的选择
答案 0 :(得分:11)
一种选择是编写一个定期检查cookie以进行更改的函数:
var checkCookie = function() {
var lastCookie = document.cookie; // 'static' memory between function calls
return function() {
var currentCookie = document.cookie;
if (currentCookie != lastCookie) {
// something useful like parse cookie, run a callback fn, etc.
lastCookie = currentCookie; // store latest cookie
}
};
}();
window.setInterval(checkCookie, 100); // run every 100 ms
答案 1 :(得分:4)
我认为我的方法更好。我写了一个自定义事件来检测何时有机会获得Cookie:
const cookieEvent = new CustomEvent("cookieChanged", {
bubbles: true,
detail: {
cookieValue: document.cookie,
checkChange: () => {
if (cookieEvent.detail.cookieValue != document.cookie) {
cookieEvent.detail.cookieValue = document.cookie;
return 1;
} else {
return 0;
}
},
listenCheckChange: () => {
setInterval(function () {
if (cookieEvent.detail.checkChange() == 1) {
cookieEvent.detail.changed = true;
//fire the event
cookieEvent.target.dispatchEvent(cookieEvent);
} else {
cookieEvent.detail.changed = false;
}
}, 1000);
},
changed: false
}
});
/*FIRE cookieEvent EVENT WHEN THE PAGE IS LOADED TO
CHECK IF USER CHANGED THE COOKIE VALUE */
document.addEventListener("DOMContentLoaded", function (e) {
e.target.dispatchEvent(cookieEvent);
});
document.addEventListener("cookieChanged", function (e) {
e.detail.listenCheckChange();
if(e.detail.changed === true ){
/*YOUR CODE HERE FOR DO SOMETHING
WHEN USER CHANGED THE COOKIE VALUE */
}
});
答案 2 :(得分:2)
如果操作Cookie的代码属于您自己,则可以使用localStorage
跟踪已更改的事件。例如,您可以在localStorage上存储垃圾以在其他选项卡上触发事件。
例如
var checkCookie = function() {
var lastCookies = document.cookie.split( ';' ).map( function( x ) { return x.trim().split( /(=)/ ); } ).reduce( function( a, b ) {
a[ b[ 0 ] ] = a[ b[ 0 ] ] ? a[ b[ 0 ] ] + ', ' + b.slice( 2 ).join( '' ) :
b.slice( 2 ).join( '' ); return a; }, {} );
return function() {
var currentCookies = document.cookie.split( ';' ).map( function( x ) { return x.trim().split( /(=)/ ); } ).reduce( function( a, b ) {
a[ b[ 0 ] ] = a[ b[ 0 ] ] ? a[ b[ 0 ] ] + ', ' + b.slice( 2 ).join( '' ) :
b.slice( 2 ).join( '' ); return a; }, {} );
for(cookie in currentCookies) {
if ( currentCookies[cookie] != lastCookies[cookie] ) {
console.log("--------")
console.log(cookie+"="+lastCookies[cookie])
console.log(cookie+"="+currentCookies[cookie])
}
}
lastCookies = currentCookies;
};
}();
$(window).on("storage",checkCookie); // via jQuery. can be used also with VanillaJS
// on the function changed the cookies
document.cookie = ....
window.localStorage["1"] = new Date().getTime(); // this will trigger the "storage" event in the other tabs.
答案 3 :(得分:2)
方法1:定期轮询
投票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);
}
用法
listenCookieChange(({oldValue, newValue})=> {
console.log(`Cookie changed from "${oldValue}" to "${newValue}"`);
}, 1000);
document.cookie = 'a=1';
方法2:API拦截
拦截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();
}
});
})();
用法
document.addEventListener('cookiechange', ({detail: {oldValue, newValue}})=> {
console.log(`Cookie changed from "${oldValue}" to "${newValue}"`);
});
document.cookie = 'a=1';
| Metric \ Method | Periodic Polling | API Interception |
| ---------------- | --------------------------- | ---------------- |
| delay | depends on polling interval | instant |
| scope | same-domain | same-origin |
答案 4 :(得分:0)
稍微改进(显示每个更改的cookie的console.log):
var checkCookie = function() {
var lastCookies = document.cookie.split( ';' ).map( function( x ) { return x.trim().split( /(=)/ ); } ).reduce( function( a, b ) {
a[ b[ 0 ] ] = a[ b[ 0 ] ] ? a[ b[ 0 ] ] + ', ' + b.slice( 2 ).join( '' ) :
b.slice( 2 ).join( '' ); return a; }, {} );
return function() {
var currentCookies = document.cookie.split( ';' ).map( function( x ) { return x.trim().split( /(=)/ ); } ).reduce( function( a, b ) {
a[ b[ 0 ] ] = a[ b[ 0 ] ] ? a[ b[ 0 ] ] + ', ' + b.slice( 2 ).join( '' ) :
b.slice( 2 ).join( '' ); return a; }, {} );
for(cookie in currentCookies) {
if ( currentCookies[cookie] != lastCookies[cookie] ) {
console.log("--------")
console.log(cookie+"="+lastCookies[cookie])
console.log(cookie+"="+currentCookies[cookie])
}
}
lastCookies = currentCookies;
};
}();
window.setInterval(checkCookie, 100);
答案 5 :(得分:0)
我们可以覆盖document.cookie
并注意Cookie的更改:
const parseCookies = (cookies = document.cookie) => cookies.split(/; (.*)/).slice(0, -1).map(cookie => {
const [name, value] = cookie.split("=")
return [name, decodeURIComponent(value)]
})
const COOKIE = Symbol("Cookie")
let lastCookies = document.cookie
let lastCookiesParsed = new Map(parseCookies(lastCookies))
Object.defineProperty(Document.prototype, COOKIE, Object.getOwnPropertyDescriptor(Document.prototype, "cookie"))
Object.defineProperty(Document.prototype, "cookie", {
enumerable: true,
configurable: true,
get() {
return this[COOKIE]
},
set(value) {
this[COOKIE] = value
if (value === lastCookies) {
return
}
for (const [name, cookieValue] of parseCookies(value).filter(([name, cookieValue]) => lastCookiesParsed.get(name) === cookieValue)) {
document.dispatchEvent(new CustomEvent("cookiechange", {
detail: {
name,
value: cookieValue
}
}));
}
lastCookies = value
lastCookiesParsed = new Map(parseCookies(lastCookies))
}
})
用法:
document.addEventListener("cookiechange", ({detail}) => {
const {name, value} = detail
console.log(`${name} was set to ${value}`)
})