众所周知javascript是单线程的,它的设计之初是为浏览器设计的GUI编程语言,GUI编程的特性之一是保证UI线程一定不能阻塞,否则体验不佳,甚至界面卡死。
所谓"单线程",就是指一次只能完成一件任务。如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推。
1.异步
所谓异步简单说就是一个任务分成两段,先执行一段,转而执行其他任务,等做好了准备转而执行第二段。
同步: 一定要等任务执行完了,得到结果,才执行下一个任务。
function taskSync = function(){
return '同步任务的返回值'
}
var result = taskSync() // 那么 result 就是同步任务的结果
otherTask() // 然后执行下一个任务
异步: 不等任务执行完,直接执行下一个任务。
function taskAsync = function(){
var result = setTimeout(function(){
console.log('异步任务的结果')
}, 3000)
return result
}
var result = taskAsync() // result 不是异步任务的结果,而是一个timeoutID
otherTask() // 立即执行其他任务,不等异步任务结束
我们拿到的 result 不是异步执行的结果,而是一个 timer id,那么要怎么拿到异步任务的结果呢?
用回调函数(callback)
改下代码如下:
function taskAsync = function(callback){
var result = setTimeout(function(){
callback('异步任务的结果')
}, 3000)
return result
}
taskAsync(function callback(result){
console.log(result) // 三秒钟后,这个 callback 函数会被执行
})
otherTask() // 立即执行其他任务,不等异步任务结束
2.callback 回调函数
概念:callback 就是(被作为参数传给另一个函数调用的)函数。
常见的callback
$('button').on(click,function(){})
click 后面的 function 就是一个回调,用户在点击的时候调用。
一般来说,只要参数是函数,那么这个函数就是回调函数。
缺点 :
- 不利于代码的阅读和维护,各个部分之间高度耦合,流程会很混乱
- 每个任务只能指定一个回调函数。
- 不能捕获异常 (
try catch
同步执行,回调函数会加入队列,无法捕获错误)