JS基础知识(四)- 异步和单线程
# 1.几道面试题(以点带面)
同步和异步的区别是什么?分别举一个同步和异步的例子
一个关于setTimeout的笔试题
前端使用异步的场景有哪些
# 2.涉及知识点
- 什么是异步(对比同步)
- 前端使用异步的场景
- 异步和单线程
# 2.1 什么是异步
异步
console.log(100);
setTimeout(function() {
console.log(200);
}, 1000);
console.log(300);
//结果:100 300 200【1s后打印】
1
2
3
4
5
6
2
3
4
5
6
同步
console.log('upload');
alert('you');
console.log('hub');
1
2
3
2
3
# 2.2 何时需要异步
- 在可能发生等待的情况
- 等待过程中不能像alert一样阻塞程序运行
- 因此,所有的“等待的情况”都不要异步
# 2.3 前端使用异步的场景
- 定时任务:setTimeout、setInterval
- 网络请求:ajax请求,动态
<img>
加载 - 事件绑定
ajax请求代码示例
console.log('start');
$.get('./data1.json', function(data(1)){
console.log(data1);
});
console.log('end');
1
2
3
4
5
2
3
4
5
img加载
console.log('start');
var img = document.createElement('img');
img.onload = function() {
console.log('loaded');
}
img.src = '/xxx.png';
console.log('end');
1
2
3
4
5
6
7
2
3
4
5
6
7
事件绑定
console.log('start');
document.getElementById('btn1').addEventListener('click',function() {
alert('clicked');
})
console.log('end');
1
2
3
4
5
2
3
4
5
# 2.4 单线程与setTimeout
console.log(100);
setTimeout(function() {
console.log(200);
});
console.log(300);
//结果: 100 300 200
1
2
3
4
5
6
2
3
4
5
6
以上程序执行过程分析:
- 执行第一行,打印100
- 执行setTimeout后,传入setTimeout的函数会被暂存起来,不会立即执行(单线程的特点,不能同时干两件事)
- 执行最后一行,打印300
- 待所有程序执行完,处于空闲状态时,会立马看有没有暂存起来的要执行。
- 发现暂存起来的setTimeout中的函数无需等待时间,就立即过来执行
# 3.对前文问题的解答
# 3.1 同步和异步的区别是什么?分别举一个同步和异步的例子
- 基于 JS 是单线程语言
- 同步会阻塞代码执行,而异步不会
- alert是同步,setTimeout 是异步
# 3.2 一个关于setTimeout的笔试题
for(var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
},i*1000)
}
//以上执行结果是:每过1s都输出5
1
2
3
4
5
6
2
3
4
5
6
修改让其每隔1s弹出0,1,2,3,4
法一:
for(var i = 0; i < 5; i++) {
(function(i) {
setTimeout(function() {
console.log(i);
},i*1000)
})(i);
}
1
2
3
4
5
6
7
2
3
4
5
6
7
法二:
for(var i = 0; i < 5; i++) {
setTimeout((function(i) {
return function() {
console.log(i);
}
})(i),i*1000)
}
1
2
3
4
5
6
7
2
3
4
5
6
7
法三:
for(let i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
},i*1000)
}
1
2
3
4
5
2
3
4
5
法四: ES7的 async/await
function sleep(interval) {
return new Promise(resolve => {
setTimeout(resolve, interval);
})
}
// 用法
async function countInAsync() {
for(let i = 0; i < 5; i++) {
console.log(i);
await sleep(1000);
}
}
countInAsync();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
setTimeout 不支持传带参数的函数