手头在维护一个比较老的项目,由于页面的重组,一些不同页面的 js 被加载到了同一个页面,导致一个页面里可能有一个以上的 window.onload ,这样做的后果就是前面的回调函数会被后面的覆盖掉。
上网搜了一下,绝大部分的解决方案有两种:
- 重载 window.onload 方法;
- 呼吁使用 window.addEventListener 。
这两种方法要么只能预防,要么需要更改老代码。我的情况比较特殊,老代码是采用 webpack 打包过的,但是配置文件不见了,之前的维护人员直接修改了打包后的代码,导致重新打包的工作量巨大,只能慢慢来。
思前想后,决定利用 Object.defineProperty 劫持 window.onload 的赋值行为,把对应的回调函数放到一个队列中集中处理。
代码如下:
/** * @function windowLoadInit - 劫持 window.onload 的赋值行为,防止覆盖 * @desc 函数调用前产生的覆盖不可逆转 * @throw {Any} 所有回调执行完毕之后,会抛出 catch 到的第一个错误 * 错误将被异步抛出,避免影响初始化函数的继续执行 * @return {Function} */ function windowLoadInit(){ const eventQueue = []; // 防止覆盖之前的 window.onload window.onload instanceof Function && eventQueue.push(window.onload); window.onload = e => { const errQueue = []; // 逐个处理回调事件 while(!!eventQueue.length){ try{ eventQueue.shift()(e); } catch(err){ errQueue.push(err); } } if(!!errQueue.length) { setTimeout(() => { throw errQueue.shift(); },0); }; }; // 每次赋值时,将回调函数添加到队列 Object.defineProperty(window, 'onload', { set: eventQueue.push }); return window.onload }
测试代码:
// 此 testCase 需在页面加载完成前执行 function testCase(){ const arr = []; window.onload = () => arr.push(-1); // 这个回调的覆盖不可避免 window.onload = () => arr.push(0); windowLoadInit(); window.onload = () => arr.push(1); window.onload = () => arr.push(2); return new Promise(resolve => { window.onload = () => resolve(arr.join('') === '012') }) } testCase().then(console.log); // true
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。