解决 window.onload 被覆盖的问题方法
作者:madRain 发布时间:2024-07-07 19:20:35
标签:window.onload,覆盖
手头在维护一个比较老的项目,由于页面的重组,一些不同页面的 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
来源:https://segmentfault.com/a/1190000021578671


猜你喜欢
- mysql-5.6.14-win32为免安装解压缩版,安装版(http://dev.mysql.com/downloads/installe
- Blender 并不是唯一一款允许你为场景编程和自动化任务的3D软件; 随着每一个新版本的推出,Blender 正逐渐成为一个可靠的 CG
- 平时经常看php的错误日志,很少有机会去自己动手写日志,看了王健的《最佳日志实践》觉得写一个清晰明了,结构分明的日志还是非常有必要的。在写日
- 什么是EfficientNet模型2019年,谷歌新出EfficientNet,在其它网络的基础上,大幅度的缩小了参数的同时提高了预测准确度
- 概述 -------------------------------------------------------------------
- 创建视图创建视图success.blade.php<!doctype html><html lang="{{ s
- 写在前面额、、、最近开始学习机器学习嘛,网上找到一本关于机器学习的书籍,名字叫做《机器学习实战》。很巧的是,这本书里的算法是用Python语
- 本文实例为大家分享了python语音整点报时的具体代码,供大家参考,具体内容如下主要的技术特殊点在于PyS60的定时器最多只能定2147秒。
- Python Logging原来真的远比我想象的要复杂很多很多,学习路线堪比git。但是又绕不过去,alternatives又少,所以必须要
- 一、基本概念查找(Searching)就是根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素(或记录)。查找表(Search
- 1.使用测量工具,量化性能才能改进性能,常用的timeit和memory_profiler,此外还有profile、cProfile、hot
- 1 前言前面的文章中我们已经获取到了基金的阶段变动信息和ETF信息的获取,那么在本章中,我们将继续前面的内容,获取基金的价格信息,并且把之前
- 安装PandasPandas是构建在Python编程语言之上的一个快速、强大、灵活且易于使用的开源数据分析和操作工具。Pandas是基于Nu
- 本节内容1、文件常用操作汇总2、打开文件3、操作文件4、关闭文件一、文件常用操作汇总二、打开文件1、普通打开模式r,英文:read,只读模式
- Flask Script扩展提供向Flask插入外部脚本的功能,包括运行一个开发用的服务器,一个定制的Python shell,设置数据库的
- 前言上位机实战开发先放一放,今天来学习一个新的内容—NumPy的使用1 一维数组例:用普通方法生成一维数组num = [0 for i in
- MySQL从5.1开始支持event功能,类似oracle的job功能。有了这个功能之后我们就可以让MySQL自动的执行数据汇总等功能,不用
- 一 例子现在,讲述一个真实的故事!故事一定是伴随着赵忠祥老师的声音开始的,雨季就要来临了,又到了动物们 * 的季节了...还记得,之前发生的作
- 问题的起源早些时候使用with实现了一版全局进程锁,希望实现以下效果:with CacheLock("test_lock"
- Linux系统下调用动态库(.so) 1、linuxany.c代码如下: #include "stdio.h"