Event Loop即事件循环,是解决javaScript单线程运行阻塞的一种机制。 主要是为了协调单线程下,事件、用户交互、脚本、UI 渲染和网络处理等行为,防止主线程的不阻塞。
因为JavaScript 是单线程,也就是说, 所有任务需要排队,前一个任务结束,才会执行后一个任务。
但是IO设备(输入、出设备)可能会因为网络等因数导致速度很慢(比如Ajax)继而CPU没有充分利用,所以设计者将IO设备的任务挂起,先执行后面的任务,等到IO设备返回了结果,再回过头,把挂起的任务继续执行下去。于是,就把所有任务分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。
只有前一个任务执行完毕,才能执行后一个任务;直接在主线程上排队执行且最先执行,形成一个执行栈
不进入主线程、而是进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",执行一个宏任务, 执行过程中如果遇到微任务,就将它添加到微任务的任务队列中 宏任务执行完毕后,再依次执行执行当前微任务队列中的所有微任务,当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染 渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)
(4)主线程不断重复上面的第三步。
"任务队列"是一个先进先出的数据结构,也是一个事件的队列(也可以理解成消息的队列),IO设备完成一项任务,就在"任务队列"中添加一个事件,表示相关的异步任务可以进入"执行栈"了。主线程读取"任务队列",就是读取里面有哪些事件。
"任务队列"中的事件,除了IO设备的事件以外,还包括一些用户产生的事件(比如鼠标点击、页面滚动等等)。只要指定过回调函数,这些事件发生时就会进入"任务队列",等待主线程读取。
所谓"回调函数"(callback),就是那些会被主线程挂起来的代码。异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数。
例子1
例子2:
例子3:
nodejs事件循环和浏览器的事件循环不一样的。浏览器的Event loop是在HTML5中定义的规范,而node中则由libuv库实现
你最终的目的应该是想在input按钮上加入点击事件吧,点击后将input的值写入cookie吧,这样
的话,给tr加事件是没有意义的,下面的代码在不引用任何构架的前提下实现的,没有使用jquery
也没有使用ExtJS,相对比较麻烦些,希望你能看懂,如果用jquery的话,更简单了,这里就不写了
function writeCookie(name, value) {// 写入cookie的代码你自己去实现
}
var rows = new Array() // 这个表格行的数组你自己组织吧,我这里只是定义一个简单的js数组,你可以从后台取这个值
// 先生成HTML代码,输出到网页上,这样才用JS绑定事件
var strHTML = ''
for(var i=0 i<rows.length i++) {
strHTML='<tr>' +
'<td><input id='btn_" + i + "' type="hidden" value='" + rows[i].id + "' /></td>' +
'<td>无关紧要的内容</td>' +
'</tr>'
}
document.writeln(strHTML)
// 绑定事件
for (var i=0 i<rows.length i++) {
var btnName = 'btn_' + i
var e = document.getElementById(btnName) // 循环取出每个按钮对象
var value = e.value // 取出按钮的值
e.onclick = function() {
writeCookie(btnName, value) // 以btnName作为键名,将按钮的值写入cookie
}
}
var p = document.getElementsByTagName('p'),p_len = p.length
for(var i = 0i < p_leni++){
p[i].onclick = function(){
alert(this.textContent)
}
}