最近开发了一个适用于iOS上的混合开发库,支持JavaScript
的开发,开发完之后对于JavaScript
中的一些特性有了更加深刻的了解。也就有了这篇文章,后续还会陆续写一些其余的关于JavaScript
的文章。javascript
异步编程
通常跟多线程
有关,而咱们都知道JavaScript
是单线程执行的,那何来异步
之说?java
事实上,但凡在
JS
中执行的代码都是单线程执行的。c++
然而,咱们日常开发JavaScript
的时候常常会提到异步编程
的概念,并且在实际的开发过程当中也常常会用到异步编程
。那先说下咱们是怎么用的,从最简单的setTimeout
提及,而后一步一步的说到ES8中的async
和await
。编程
setTimeout(function(){
console.log('timeout');
},1000);
复制代码
执行上面的代码1秒后输出timeout
。下面换一种方式,使用setInterval
来实现。浏览器
var interval = setInterval(function () {
console.log('timeout');
clearInterval(interval);
}, 1000);
复制代码
上面两种方式实现的效果是同样的,都是在等待1秒后执行function
中的代码。多线程
看到上面的代码,但凡写过其余语言的好比:c++、java、OC等的,都知道这其实就是一个定时器,而setTimeout
稍微特殊点,只会执行一次,而setInterval
可以执行屡次,直到显示取消为止。异步
举上面的例子主要是说明,在JavaScript中,setTimeout
和setInterval
能够实现相似异步的效果。async
不一样的语言对于定时器的实现方式有可能不同,甚至同一种语言,提供多种不一样的定时器API,就拿
Objectiv-c
来讲,起码有三种方式实现定时器的效果,可是无论什么语言,用什么方式来实现,工做原理差很少,异步编程
就是当
定时器
获取到某个信号
的时候,在建立该定时器的线程中插入任务。这样的过程能够理解为线程调度。由于定时信号
不必定在你回调的线程上触发的,该信号
有可能直接由硬件中断
产生,也有多是软件模拟
产生,可是在使用的时候都会在建立的线程得到回调。ui
所以,定时器本质上仍是单线程的,跟异步编程
不要紧。我举个例子你就明白了
var t1 = new Date();
setTimeout(function(){
var t2 = new Date();
console.log('diff:'+(t2-t1));
},1000);
while (new Date() - t1 < 2000) {
}
复制代码
上面的代码你以为是输出1000
呢?仍是2000
?
实际的代码输出是diff:2000
,具体是2000多少要看实际状况。举这样的例子说明什么呢,正是说明setTimeout
仍是串行执行的,你能够理解为见缝插针
方式。所以setTimeout
压根就算不上异步
。
一个残酷的现实是,javascript
中不存在真的异步
,一切异步
都是假象。
全部的JS代码都是在同一个线程上执行的,所以不存在多线程的概念,也就不存在真正的异步编程。
其实某些浏览器支持
worker
API,算是真的多线程。可是本篇不作介绍。
既然本篇的主题是异步编程
,那么就算是假象,也得继续了。
我记得JS的异步编程的概念被提出来是从XMLHttpRequest
(Ajax)开始的,而这里的异步指的只是实际的http请求
是在非JS线程执行的,而请求完毕
后的回调仍是在JS线程执行的。这样看起来是异步的,可是咱们要注意到,http异步请求
不是在JS线程上执行的,而是由浏览器负责的,跟JS不要紧。可是,正是由于有了这样的模型,才使得一些本来没法实现的功能变得可能。