js基础-异步,同步,单线程

js执行环境是‘单线程’

什么是单线程(single thread)?

指一次只能完成一件任务。

如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推

 

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

坏处:只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行。

常见的浏览器无响应(假死),往往就是因为某一段Javascript代码长时间运行(比如死循环),导致整个页面卡在这个地方,其他任务无法执行。

 

为了解决单线程这问题,Javascript语言将任务的执行模式分成两种:同步(Synchronous)和异步(Asynchronous)

 

同步模式:

1)前一个任务完成后,执行下一个任务。

2)程序的执行顺序与任务的排列顺序是一致的、同步的;

 

异步模式:

1)前一个任务结束后,不是执行后一个任务,而是执行回调函数,

     后一个任务不等前一个任务结束就执行

2)程序的执行顺序与任务的排列顺序是不一致的、异步的

 

简言之:同步会堵塞代码执行,而异步不会。

 

js异步运行机制之微任务和宏任务

异步执行的运行机制如下(同步任务也如此,因为它可以被视为没有异步任务的异步执行):

  1.所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)

 

  2.主线程之外,还存在一个“任务队列”,只要异步任务有了运行结果,就在“任务队列”之中放置一个事件

 

  3.一旦“执行栈”中的所有同步任务执行完毕,系统就会读取“任务队列”,看看里面有哪些事件。那些对应的异步任务,于是结束等待,进入执行栈,开始执行

 

  4.主线程不断重复第3步

 

微任务和宏任务

macro-task(宏任务):包括整体代码script,setTimeout,setInterval

micro-task(微任务):Promise,process.nextTick

任务队列:宏任务队列 、微任务队列

不同类型的任务会进入不同的任务队列(Event Queue)

事件循环的顺序,决定js代码的执行顺序。进入整体代码(宏任务)后,开始第一次循环。接着执行所有的微任务。

然后再次从宏任务开始,找到其中一个任务队列执行完毕,再执行所有的微任务。

 

例子1:

 1 setTimeout(function() {
 2     console.log('setTimeout');
 3 })
 4 
 5 new Promise(function(resolve) {
 6     console.log('promise');
 7     //resolve();
 8 }).then(function() {
 9     console.log('then');
10 })
11 
12 console.log('console');

 结果:promise console setTimeout

说明:

1 整段代码作为宏任务进入主线程
2 遇到settimeout,将其回调函数注册后分发到宏任务Event Queue。
3 遇到了Promise,new Promise立即执行,then函数分发到微任务Event Queue
4 遇到console.log(),立即执行
5 第一个宏任务执行结束,看看有什么微任务,发现有then,执行 
6 第二轮循环,发现宏任务settimeout的回调函数,执行。
7 结束。

例子2:

 1 console.log('1');
 2 
 3 setTimeout(function() {
 4     console.log('2');
 5     process.nextTick(function() {
 6         console.log('3');
 7     })
 8     new Promise(function(resolve) {
 9         console.log('4');
10         //resolve();
11     }).then(function() {
12         console.log('5')
13     })
14 })
15 process.nextTick(function() {
16     console.log('6');
17 })
18 new Promise(function(resolve) {
19     console.log('7');
20     //resolve();
21 }).then(function() {
22     console.log('8')
23 })
24 
25 setTimeout(function() {
26     console.log('9');
27     process.nextTick(function() {
28         console.log('10');
29     })
30     new Promise(function(resolve) {
31         console.log('11');
32         //resolve();
33     }).then(function() {
34         console.log('12')
35     })
36 })
结果:1,6,7,2,3,4,9,10,11  

例子3:例子2升级版

 1 console.log('1');
 2 
 3 setTimeout(function() {
 4     console.log('2');
 5     process.nextTick(function() {
 6         console.log('3');
 7     })
 8     new Promise(function(resolve) {
 9         console.log('4');
10         resolve();
11     }).then(function() {
12         console.log('5')
13     })
14 })
15 process.nextTick(function() {
16     console.log('6');
17 })
18 new Promise(function(resolve) {
19     console.log('7');
20     resolve();
21 }).then(function() {
22     console.log('8')
23 })
24 
25 setTimeout(function() {
26     console.log('9');
27     new Promise(function(resolve) {
28         console.log('11');
29         resolve();
30     }).then(function() {
31         console.log('12')
32     })
33 })
结果 :1,6,7,8, 2,3,4,5, 9,11,12

同步场景

如:alert()  prompt()

 

**前端使用异步场景

在可能发生等待的情况

  1).定时任务:setTimeout setInterval

  2).网络请求:ajax请求,动态<img>加载

  3).事件绑定:addEventListener

例子1:

1     console.log(100);
2     setTimeout(function(){
3       console.log(200);
4     },1000);
5     console.log(300);

  结果:100 300 200

例子2:

1     console.log('img开始');
2     var img = document.createElement('img');
3     img.onload = function(){
4       console.log('loaded');
5     }
6     img.src="/xxx.png";
7     console.log('img结束');

     结果:img开始  img结束  loaded

例子3:

1     console.log('事件开始!');
2     var btn1 = document.getElementById('btn1');
3     btn1.addEventListener('click',function(){
4       console.log('你点击我了');//点击了才会显示
5     })
6     console.log('事件结束!!');

  结果:事件开始!  事件结束! 你点击我了

例子4:

1     console.log(1);
2     setTimeout(function(){
3       console.log(2);
4     },1500);
5     console.log(3);
6     setTimeout(function(){
7       console.log(4);
8     },300);
9     console.log(5);

  结果:   1 3 5 4 2   //根据封禁时间解封

 

转载于:https://www.cnblogs.com/lingXie/p/11493925.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值