异步和单线程
1、异步的使用场景
异步:中间的步骤根本没有阻塞接下来程序的运行,
同步:中间的步骤阻塞了后面程序的运行。
【`alert`是同步,`setTimeout`是异步】
JS 脚本用到异步的场景主要有三个:
- 定时 `setTimeout` `setInverval`
- 网络请求,如 `ajax` `<img>`加载
- 事件绑定
网络请求类
//ajax 代码示例 console.log('start') $.get('./data1.json', function (data1) { console.log(data1) }) console.log('end') //img 代码示例(常用语打点统计) console.log('start') var img = document.createElement('img') img.onload = function () { console.log('loaded') } img.src = '/xxx.png' console.log('end')
//事件绑定 console.log('start') document.getElementById('btn1').addEventListener('click', function () { alert('clicked') }) console.log('end')
//定时 `setTimeout` `setInverval` console.log(100) setTimeout(function () { console.log(200) }, 1000) console.log(300)
2、单线程是如何实现异步
console.log(100) setTimeout(function () { console.log(200) }) console.log(300)
单线程:事情都是一步一步做的,不能两件事儿一起做。
- 执行第一行,打印`100`
- 执行`setTimeout`后,传入`setTimeout`的函数会被暂存起来,不会立即执行。
- 执行最后一行,打印`300`
- 待所有程序执行完,处于空闲状态时,会立马看有没有暂存起来的要执行。(任务的封闭时间为:从放到暂存区开始计时,到任务满足条件可执行时解封)
- 发现暂存起来的`setTimeout`中的函数无需等待时间,就立即来过来执行
规则和上面的一样,只不过这里暂存起来的函数,需要等待 1s 之后才能被执行。 ```javascript console.log(100) setTimeout(function () { console.log(200) }, 1000) console.log(300) ``` 下面再来一个 ajax 的例子。规则也是一样的,只不过这里暂存起来的函数,要等待网络请求返回之后才能被执行,具体时间不一定。 ```javascript console.log(100) $.get('./data.json', function (data) { console.log(200) }) console.log(300) ``` 事件绑定的实现原理,也是会把时间暂存,但是要等待用户点击只有,才能被执行。原理是一样的,因此事件绑定在原理上来说,可以算作是异步。但是从设计上来说,还是分开好理解一些。 ```javascript console.log(100) $btn.click(function () { console.log(200) }) console.log(300) ```