1、什么是异步
2、异步进化史
回调函数 —> Promise —> Generator —> async/await。
3、同步异步举例
// 异步 (callback 回调函数)
console.log(100)
setTimeout(function(){
console.log(200)
},1000)
console.log(300)
//100
//300
//200
// 同步
console.log(100)
alert(200)
console.log(300)
//100
//200
//300
4、异步应用场景
4.1 网络请求,如ajax图片加载
// ajax
console.log('start')
$.get('./data1/json',function(data1){
console.log(data1)
})
console.log('end')
4.2 定时任务,如setTimeout
//图片加载
console.log('start')
let img = document.createElement('img')
img.onload = function(){
console.log('loaded')
}
img.src = '/xxx.png'
console.log('end')
4.3 事件监听、绑定
// 事件监听
document.getElementById('#myDiv').addEventListener('click', function (e) {
console.log('我被点击了')
}, false);
5、回调地狱
当回调只有一层的时候感觉没有什么问题,但是一但嵌套层级过多,代码可读性和可维护性就变差。
const https = require('https');
https.get('目标接口1', (res) => {
console.log(data)
https.get('目标接口2', (res) => {
https.get('目标接口3'), (res) => {
console.log(data)
https.get('目标接口4', (res) => {
https.get('目标接口5', (res) => {
console.log(data)
.....
// 无尽的回调
}
}
}
}
})
6.典型题
6.1 同步与异步的区别
- 基于JS是单线程语言
- 异步不会阻塞代码执行
- 同步会阻塞代码执行
6.2 异步加载图片
function loadImg(src){
return new promise(
(resolve,reject)=>{
const img = document.createElement('img')
img.onload = () => {
resolve(img)
}
img.onerror=() => {
reject(new Error(`图片加载失败`))
}
img.src = src
}
)
}
const url1 = 'xxx'
const url2 = 'xxx'
loadImg(url).then(img=>{
console.log(img1.width)
return img1 //普通对象
}).then(img1=>{
console.log(img.height)
return loadImg(url2) //promise实例
}).then(img2=>{
console.log(img2.height)
}).catch(ex=>console.log(ex))
6.3 setTimeout场景题
// setTimeout笔试题
console.log(1)
setTimeout(function(){
console.log(2)
},1000)
console.log(3)
setTimeout(funcion()=>{
console.log(4)
},0)
console.log(5)
//1 3 5 4 2
6.4 回调函数有什么缺点?如何解决回调地狱问题?
回调函数有一个致命的弱点,就是容易写出回调地狱(Callback hell)。假设多个请求存在依赖性,你可能就会写出如下代码:
ajax(url, () => {
// 处理逻辑
ajax(url1, () => {
// 处理逻辑
ajax(url2, () => {
// 处理逻辑
})
})
})
回调地狱的根本问题就是:
- 嵌套函数存在耦合性,一旦有所改动,就会牵一发而动全身
- 嵌套函数一多,就很难处理错误
当然,回调函数还存在着别的几个缺点,比如不能使用 try catch
捕获错误,不能直接 return
。
解决方法:使用Promise;