每一个故事都有由来。前两天在看 gulp
的时候,看到了它有个 promise
的玩意儿,而后的而后,这两天就掉进了 javascript
的异步和回调的坑里面去了。
其间搜索了 javascript promise
,看到了一堆好文章。大概给个 List 吧。javascript
看得昏天黑地,大概也理清楚了一点,作个小总结。html
上面这些文章写得都挺好,但大部分都是上来直接说怎么异步回调,js的异步有哪些方法。这适合高级选手。我刚开始连啥是异步,啥是回调都不太清楚,这些方法天然也比较难理解。因此仍是打好基础,先弄清楚异步、回调这些基本概念比较好。java
先看个例子。gulp
javascriptfoo(); bar();
同步
的(synchronous),即按照书写的顺序执行。在上述例子中,bar 方法会在 foo 方法执行完以后,再执行。异步
(asynchronous)与同步相对,即在前一个方法未执行完时,就开始运行后一个方法。在上述例子中,先执行 foo 方法,foo 方法没执行完,就开始执行 bar 方法。从异步的概念中能够发现,程序异步运行,能够提升程序运行的效率,没必要等一个程序跑完,再跑下一个程序,特别当这两个程序是无关的时候。两个程序在必定时间内,能够是同时运行的。写服务器的时候应该会碰到不少这样的例子。能够想象,若是服务器的程序都是同步的,那并发什么的就不存在了吧。segmentfault
这一点是我本身简单的理解。promise
阻塞
就是说一个程序没运行完,它后面的程序是没法运行的。非阻塞
则相反,一个程序若是由于各类缘由(网络、代码量等)没运行完的时候,其余的程序也是能够继续运行的。这一点也是我本身的简单理解。服务器
单线程
是指程序运行只有一个通道,不一样的方法须要排队执行。多线程
的功能,至关于开了几个通道运行程序,使得程序能够在不一样的线程中运行,不会相互影响。从上述基本概念中能够发现,异步若是发生在多线程语言中,会十分天然且符合逻辑。异步本质上应该就是多线程语言的产物。由于只有在多线程语言中才可以实现程序之间相互不干扰,不产生阻塞。网络
有了上面的一些基本概念,那么下面来讲说正题,JS中的异步。
咱们都知道 JS 是一个单线程的语言,永远只有一个通道在运行程序。那么既然它是个单线程又如何会有异步呢?
JS 中所谓的异步,应该被称为伪异步(pseudo asynchronous)。这是由于 JS 语言中的异步,会产生阻塞,并会相互干扰。多线程
setTimeout
咱们来看一下 setTimeout 如何模拟 JS 中的异步。并发
javascriptvar foo = function(){ console.log('foo begins'); setTimeout(function(){ console.log('foo finishes'); },1000); }; var bar = function(){ console.log('bar executed'); } foo(); bar();
上述过程执行的时候,会打印出
foo begins
bar executed
foo finishes
因此,在上述代码块中,在前一方法(foo)执行时,后一方法(bar)也能够执行。符合异步的基本概念,程序并不按顺序执行。
说是模拟是由于,你能够把 console.log('foo begins');
理解成会运行 1 秒的一个代码行,运行完后,会跳出foo finishes
。而中间这 1 秒运行的时候,后面的 bar 方法也是能够运行的。这样就模拟了一个异步的效果。
咱们将上述代码块稍作修改
javascriptvar foo = function(){ console.log('foo begins'); setTimeout(function(){ console.log('foo finishes'); },1000); }; var bar = function(){ while(){ } } foo(); bar();
你会发现 1 秒以后 foo finishes
并无被打印出来。这是由于 bar 方法是个死循环,使得 js 引擎假死,致使了 foo 方法也没有被运行完。若是是多线程的异步,假死的应该是运行 bar 方法的线程,而 foo 方法仍然会按预期打印出 foo finishes
。固然了,其实这个死循环也只是模拟 bar 方法块程序运行的时间将很长。实际上,若是 bar 方法运行的时间超过了 1 秒,比方说是 5 秒,那么 foo finishes
也将在 5 秒以后被打印出来。这个本质上取决于 JS 单线程程序块按队列执行的特性。
因此 JS 中的异步并不能像普通的异步同样,实现非阻塞和不干扰。
虽然 JS 中的异步有其先天的缺陷,可是这种异步的思想,仍然能被 JS 程序开发人员所借鉴。毕竟,异步是能够大大提升程序运行效率的。
也正是因为 JS 自己是单线程程序的关系,因此 JS 中异步的实现,并不能像其余语言同样,简单地多开个线程就能够解决。
目前我看的集中方法主要有回调、事件类方法、promise等。
先说说回调是什么吧。回调
(callback)这种名词就跟函数
(function)同样,乍一看是比较难懂的,至少我是这样的。
根据sf上这个问答的解释,能够明确,把一个函数做为参数传入到另外一个函数中,那么这个做为参数的函数就叫作回调函数。如:
javascriptvar foo = function(callback){ // foo method callback(); }; foo(bar);
其中,bar 就是一个回调函数。固然了,按我我的的理解,应该说是 bar 是 foo 的回调函数。
时间问题,具体的实现方式和理解还没好好看,往后再作细细梳理。上述理解若有偏颇,欢迎讨论指正。