人嘛,大多总有点情怀,程序员当然不例外。写出了满意的代码,自然免不了自得一番。
上代码:
function draw_curve(){ var canvas = document.getElementById("LINE_CANVAS"); var w = new Array(7); w[0] = Number($("#w0").val()); w[1] = Number($("#w1").val()); w[2] = Number($("#w2").val()); var x = -300; var tid = setInterval(function(){ var ys = getYValue(x, 0, w); for(var i = 0;i < ys.length;i++){ addPoint(canvas,x + 300,300 - ys[i]); } if (x < 300) { x++; } else { clearInterval(tid); } } , 0.1) }
为什么自得呢?我们知道浏览器js引擎实际上是以单线程的方式运行,而js引擎线程和界面渲染线程又是互斥的,这就可能导致界面元素不能得到及时更新,上述代码避免了这个问题。
上述代码片段是一个button的事件响应函数,主要完成绘图工作,由于涉及到神经网络中的复杂模型,函数getYValue(x, 0, w)是非常耗时间的过程,如果采用平凡的方法,将会导致界面“阻塞”,直到计算完成后才能在界面上显示分界曲线。但如果采用上述代码模拟线程并发,既可以一边更新数据一边更新界面,还可以做到“并发”的响应用户多次点击button,“齐头并进”画出多条曲线。
浏览器进程简介
浏览器内核当然是允许多线程并发的,包括js引擎线程,界面渲染线程,用户事件响应线程,定时事件响应线程,HTTP请求状态更新通知线程等等,他们之间的通信依靠一个任务队列,每个任务实际上就是我们的函数体。
用户事件响应线程,定时事件响应线程,HTTP请求状态更新通知线程三个线程可以向任务队列添加任务,而js引擎线程负责按顺序执行任务队列中的任务,同时界面渲染线程和js引擎线程相对于数据的更新必须互斥,否则可能导致数据之间的不一致性。想要模拟多线程并发,采取的方式就是把大任务打散成为许多小任务,每个小任务定义在一个定时回调函数中,实现并发。
详细信息参看本博客的“机器学习”分类。