关于JS中同步和异步的一点说明

  大家可能都知道,JS语言的执行环境是单线程的。

所谓单线程就是指一次只能完成一件任务,如果有多个任务,就必须排队,等前面一个任务执行完成,再执行后面一个任务,依次进行。

好处:实现起来比较简单,执行环境相对单纯。

缺点:只要存在一个任务耗时很久,后面的任务都必须排队等着,会拖延整个程序的执行。常见的浏览器无响应(假死)往往就是因为某一段JS代码长时间运行(比如死循环),导致整个页面卡在某个任务,其它任务无法执行。

那么为了解决这个问题。JS将任务的执行模式分为两种:同步(synchronous) 和 异步(asynchronous)。

同步上面已经介绍过,即后一个任务等前一个任务结束后再执行,程序的执行顺序与任务的排列顺序是一致的、同步的。

异步模式则完全不同,每一个任务有一个多多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序不是一致的。

异步模式非常重要。在浏览器端,耗时很长的操作都应该是异步执行,避免浏览器失去响应,最好的列子就是ajax操作。

异步调用不会阻止代码的顺序执行,而是在将来的某一个时刻触发设置好的逻辑,所以我们:

1.并不知道逻辑什么时候会被调用;

2.只能定义当触发的时候逻辑是什么;

3.只能等待,同时可以去处理其他的逻辑;

setTimeout就是这样的一个异步调用。

var a = 1;
function f1(a){
console.log("I am in f1");
setTimeout(function(){a+=2;console.log("f1:" + a);},1000)}
f1(a);
console.log("out:" + a);

 

得到的结果如下图所示:

I am in f1
out:1
f1:3

结果表明代码执行过程中确实是先执行了f1函数,在执行console.log输出后,setTimeout的回调函数在执行过程中被挂起,知道1s后才被调用,在等待执行setTImeout回调函数的时间里,JS选择执行后面的任务,即执行了console.log("out:" + a);

实际上,异步函数,如setTimeout和setInterval,是被压入了称之为Event Loop的队列。

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

 

posted on 2018-03-07 11:19  Joker陈  阅读(3347)  评论(0编辑  收藏  举报

导航