js Event Loop 事件循环

JavaScript015

js Event Loop 事件循环,第1张

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)

    }

}