要了解什么是异步与回调先举两个例子
设定两个投骰子的程序
第一个程序:
设定骰子运行3秒钟后会停下来,在三秒内不断地去读取骰子输出的结果,没有结果则不做任何事情,有结果时则输出骰子点数。
const 摇色子 = () => {
const t = new Date()
while (new Date() - t < 3000) {
}
const n = Math.floor(Math.random() * 6) + 1
console.log(`点数为 ${n}`)
return n
}
console.log(1)
const result = 摇色子()
console.log(2)
最终输出的结果是
第二个程序:
使用setTimeout,调用投骰子函数后三秒后执行函数,函数执行完成后输出结果
const 摇色子 = () => {
setTimeout(() => {
const n = Math.floor(Math.random() * 6) + 1
console.log(`点数为 ${n}`)
return n
}, 3000)
}
console.log(1)
const result = 摇色子() // result === undefined
console.log(2)
最终输出的结果是
这种执行一个函数,却不等待函数返回结果的形式就是异步
两段代码的区别
代码1
重复:JS 不停查看当前时间(每秒查看几百次)
顺序:代码执行顺序符合习惯
结果:result 可以获取色子点数 n
代码2
队列:JS 不看时间,直接把函数放到任务队列(时间过了自动调用)
顺序:代码执行顺序不符合习惯
结果:result 获取不到色子点数 n
异步的定义
如果你执行一个函数,却不等待函数返回结果那么我们就说你异步地执行了这个函数或者说,你执行了一个异步函数
异步的特征
含有 setTimeout/queueMicrotask/AJAX 的函数,很有可能是异步函数
两种拿到异步代码的结果的方法
异步代码拿不到结果,只有使用轮询和回调两种方法才可以拿得到结果
轮询
每几秒就查看一次某变量
let m = -1
const 摇色子 = () => {
setTimeout(() => {
const n = Math.floor(Math.random() * 6) + 1
console.log(`点数为 ${n}`)
m = n
}, Math.random() * 100)
return undefined
}
console.log(1)
const result = 摇色子() // result === undefined
setInterval(() =>{
if (m !== -1){
console.log(m)
}
},3000)
console.log(2)
设置一个全局变量,在出现结果的时候把结果复制到全局变量上
回调
把函数当作参数,传给函数
const 摇色子 = (f) => {
setTimeout(() => {
const n = Math.floor(Math.random() * 6) + 1
console.log(`点数为 ${n}`)
f(n)
}, 3000)
}
console.log(1)
const f = (n) => console.log('n',n)
const result = 摇色子(f) // result === undefined
console.log(2)
将函数作为参数传入使用,出现结果n时将n作为参数,调用传入的函数。这样就可以获得结果了