深刻理解javascript编程中的同步和异步

JavaScript的优点之一是其如何处理异步代码。异步代码会被放入一个事件队列,等到全部其余代码执行后才进行,而不会阻塞线程。然而,对于初学者来讲,书写异步代码可能会比较困难。而在这篇文章里,我将会消除你可能会有的任何困惑。
理解异步代码javascript

JavaScript最基础的异步函数是setTimeout和setInterval。setTimeout会在必定时间后执行给定的函数。它接受一个回调函数做为第一参数和一个毫秒时间做为第二参数。如下是用法举例:html

console.log( "a" );
setTimeout(function() {
    console.log( "c" )
}, 500 );
setTimeout(function() {
    console.log( "d" )
}, 500 );
setTimeout(function() {
    console.log( "e" )
}, 500 );
console.log( "b" );

正如预期,控制台先输出“a”、“b”,大约500毫秒后,再看到“c”、“d”、“e”。我用“大约”是由于setTimeout事实上是不可预知的。实际上,甚至 HTML5规范都提到了这个问题:html5

“这个API不能保证计时会如期准确地运行。因为CPU负载、其余任务等所致使的延迟是能够预料到的。”java


有趣的是,直到在同一程序段中全部其他的代码执行结束后,超时才会发生。因此若是设置了超时,同时执行了需长时间运行的函数,那么在该函数执行完成以前,超时甚至都不会启动。实际上,异步函数,如setTimeout和setInterval,被压入了称之为Event Loop的队列。node

Event Loop是一个回调函数队列。当异步函数执行时,回调函数会被压入这个队列。JavaScript引擎直到异步函数执行完成后,才会开始处理事件循环。这意味着JavaScript代码不是多线程的,即便表现的行为类似。事件循环是一个先进先出(FIFO)队列,这说明回调是按照它们被加入队列的顺序执行的。JavaScript被 node选作为开发语言,就是由于写这样的代码多么简单啊。jquery

Ajaxweb

异步Javascript与XML(AJAX)永久性的改变了Javascript语言的情况。忽然间,浏览器再也不须要从新加载便可更新web页面。 在不一样的浏览器中实现Ajax的代码可能漫长而且乏味;可是,幸好有jQuery(还有其余库)的帮助,咱们可以以很容易而且优雅的方式实现客户端-服务器端通信。ajax

咱们可使用jQuery跨浏览器接口$.ajax很容易地检索数据,然而却不能呈现幕后发生了什么。好比:编程

var data;
$.ajax({
    url: "some/url/1",
    success: function( data ) {
        // But, this will!
        console.log( data );
    }
})
// Oops, this won't work...
console.log( data );

较容易犯的错误,是在调用$.ajax以后立刻使用data,可是其实是这样的:promise

xmlhttp.open( "GET", "some/ur/1", true );
xmlhttp.onreadystatechange = function( data ) {
    if ( xmlhttp.readyState === 4 ) {
        console.log( data );
    }
};
xmlhttp.send( null );

底层的XmlHttpRequest对象发起请求,设置回调函数用来处理XHR的readystatechnage事件。而后执行XHR的send方法。在XHR运行中,当其属性readyState改变时readystatechange事件就会被触发,只有在XHR从远端服务器接收响应结束时回调函数才会触发执行。

处理异步代码

异步编程很容易陷入咱们常说的“回调地狱”。由于事实上几乎JS中的全部异步函数都用到了回调,连续执行几个异步函数的结果就是层层嵌套的回调函数以及随之而来的复杂代码。

Node.js中的许多函数也是异步的。

JavaScript 使得编写异步代码很容易. 使用 promises, 事件, 或者命名函数来避免“callback hell”. 

相关文章
相关标签/搜索