关于异步回调的一段代码及相关总结

昨天遇到了一个问题,就是想在外部js里实现页面加载完了就执行js,类似于jquery中$或者window.onload,当然和window.onload还有所不同,因为window.onload是在图片啊其他的资源加载完了才开始执行的,而我想在尽可能快的执行,问题可以用一段代码来描叙:

 1 <html>
 2 <head>
 3 <script src="test.js“></script>
 4  
 5 </head>
 6 <body>
 7 
 8 <p id="hehe"></p>
 9 
10 </body>
11 
12 </html>

test.js代码:

alert(document.getElementById("hehe");

  经过执行之后我们发现,alert返回null,按理应该返回object才对,因为我们alert了一个对象,之所以会产生这种情况,就是js先于domtree的建立,解决这种问题,当然一般我们可以换种写法,用window.onload,也可以按照yahoo优化网站的35条建议把<script>放到代码底部。也可以在外部js里强行僵化的用setTimeout(fn,seconds)来设置时间,但是博主不想这样,想一劳永逸并且尽可能优雅的解决问题,求助之后大神给了如下代码:

 1 var isReady = false;
 2 var readyList = [];
 3 
 4 function ready(fn) {
 5   if (isReady) {
 6     setTimeout(function () {
 7       fn()
 8     }, 0);
 9     return;
10   }
11   readyList.push(fn);
12 }
13 
14 function setReady() {
15   if (isReady) {
16     return;
17   }
18 
19   isReady = true;
20   for (var i = 0, n = readyList.length; i < n; i++) {
21     readyList[i]();
22   }
23   readyList.length = 0;
24 }
25 
26 (function () {
27   if (document.readyState === 'complete') {
28     setTimeout(setReady, 0);
29   } else {
30     document.addEventListener('DOMContentLoaded', setReady);
31     window.addEventListener('load', setReady);
32   }
33 }());

我一开始没有理解异步回调,所以百思不得其解,后来有幸有人告诉我这是回调这才豁然开朗,其实setTimeout()这不也是一种异步回调的写法吗?

上述代码中

document.addEventListener('DOMContentLoaded', setReady);
window.addEventListener('load', setReady);这就是异步回调addEventListener和setTimeout都是异步回调的写法,在setTimeout中setTimeout(fn,seconds)但seconds条件未满足即此条件未触发时,js程序挂起,页面构建domtree渲染,但事件发生之后,中断页面渲染,执行js代码,类似的可以理解addEventListener函数。异步回调之后就可以达到我们的目的

这就是异步回调 addEventListener和setTimeout都是异步回调的写法,在setTimeout中setTimeout(fn,seconds)但seconds条件未满足即此条件未触发时,js程序挂起,页面构建domtree渲染,但事件发生之后,中断页面渲染,执行js代码,类似的可以理解addEventListener函数。 异步回调之后就可以达到我们的目的,大神给的代码中,有队列还有全局标记,功能很多,处理很全面,为了理解核心部分,我做一个简化,html代码不变,js代码改为:

 1 //var isReady = false;
 2 //var readyList = [];
 3 var a={};
 4 
 5 function ready(fn) {
 6   //if (isReady) {
 7  //   setTimeout(function () {
 8   //    fn()
 9  //   }, 0);
10   //  return;
11  // }
12 a.fn=fn;
13 }
14 
15 function setReady() {
16   a.fn();
17 }
18 
19 (function () {
20   if (document.readyState === 'complete') {
21     setTimeout(setReady, 0);
22   } else {
23     document.addEventListener('DOMContentLoaded', setReady);
24     window.addEventListener('load', setReady);
25   }
26 }());

这样注释掉一些部分理解起来就容易了,但是请注意,这样因为有两个事件和两个回调会执行两次fn()。

关于回调还可以参加阮一峰老师的博客,写的很好http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html 我打算转载过来。

原文地址:https://www.cnblogs.com/admos/p/4427852.html