response = Faraday.get "http://www.google.com"puts responseputs "Done!"执行路径很容易跟踪:
request("http://www.google.com", function(error, response, body) { console.log(body);}); console.log("Done!");表面上看略有不同,实际行为截然不同:
回调函数的调用在调用栈作为初始化frame(片段),由于JavaScript是单线程的,未来的消息提取和处理因为等待栈的所有调用返回而被停止。后续(同步)函数调用会添加新的调用frame到栈(例如,函数init调用函数changeColor)。
function init() { var link = document.getElementById("foo");link.addEventListener("click", function changeColor() {this.style.color = "burlywood"; });} init();在这个例子中,当用户单击“foo”元素时,一条消息(及其回调函数changeColor)会被插入到队列,并触发“onclick“事件。当消息离开队列时,其回调函数changeColor被调用。当changeColor返回(或者是抛出一个错误),事件循环仍在继续。只要函数changeColor存在,并指定为“foo”元素的onclick方法的回调,那么在该元素上单击会导致更多的消息(和相关的回调changeColor)插入队列。function f() { console.log("foo"); setTimeout(g, 0); console.log("baz"); h();} function g() { console.log("bar");} function h() { console.log("blix");} f();由于setTimeout的非阻塞特性,它的回调将在至少0毫秒后触发,而不是作为消息的一部分被处理。在这个示例中,setTimeout被调用, 传入了一个回调函数g且延时0毫秒后执行。当我们指定时间到达(当前情况是,几乎立即执行),一个单独的消息将被加入队列(g作为回调函数)。控制台打印的结果会是像这样:“foo”,“baz”,“blix”,然后是事件循环的下一个动作:“bar”。如果在同一个调用片段中,两个调用都设置为setTimeout -传递给第二个参数的值也相同-则它们的回调将按照调用顺序插入队列。
首先,我们的worker:
// our worker, which does some CPU-intensive operationvar reportResult = function(e) { pi = SomeLib.computePiToSpecifiedDecimals(e.data); postMessage(pi);}; onmessage = reportResult;然后,主要的代码块在我们的HTML中以script-标签存在:// our main code, in a <script>-tag in our HTML pagevar piWorker = new Worker("pi_calculator.js");var logResult = function(e) { console.log("PI: " + e.data);}; piWorker.addEventListener("message", logResult, false);piWorker.postMessage(100000);在这个例子中,主线程创建一个worker,同时注册logResult回调函数到其“消息”事件。在worker里,reportResult函数注册到自己的“消息”事件中。当worker线程接收到主线程的消息,worker入队一条消息同时带上reportResult回调函数。消息出队时,一条新消息发送回主线程,新消息入队主线程队列(带上logResult回调函数)。这样,开发人员可以将cpu密集型操作委托给一个单独的线程,使主线程解放出来继续处理消息和事件。function changeHeaderDeferred() { var header = document.getElementById("header");setTimeout(function changeHeader() {header.style.color = "red"; return false; }, 100);return false;} changeHeaderDeferred();在这个例子中,changeHeaderDeferred函数被执行时包含了变量header。函数 setTimeout被调用,导致消息(带上changeHeader回调)被添加到消息队列,在大约100毫秒后执行。然后 changeHeaderDeferred函数返回false,结束第一个消息的处理,但header变量仍然可以通过闭包被引用,而不是被垃圾回收。当 第二个消息被处理(changeHeader函数),它保持了对在外部函数作用域中声明的header变量的访问。一旦第二个消息 (changeHeader函数)执行结束,header变量可以被垃圾回收。