同步:synchronous: 指全部任务按出现的前后顺序依次执行 若是出现阻塞的任务,那么线程就会等待这个任务完成,接着执行下一个任务。javascript
异步:asynchronous:不保证全部任务按出现的顺序执行html
并发:concurrent:从宏观上,某个时间段里面多个程序都获得了运行,但不是说“同时运行”java
并行:parallel:在多核心下,因进程和线程独立运行,且多个线程之间共享数据,程序能够同时运行。jquery
经常使用的回调函数有:git
https://zhuanlan.zhihu.com/p/...github
做用:延迟指定的时间来调用函数或计算表达式。web
语法:setTimeout(func /**函数,必选*/,code /**表达式,可选*/ ,milliseconds /**执行需等待的毫秒数,必选*/param1, param2, .../**传递给函数的参数,可选*/)
ajax
具体用法参加《Javascript异步编程(一)》编程
做用:按照指定的周期(以毫秒计)来调用函数或计算表达式。浏览器
语法:setInterVal(func /**函数,必选*/,code /**表达式,可选*/ ,milliseconds /**每次执行将延迟的毫秒数,必选*/param1, param2, .../**传递给函数的参数,可选*/)
console.log('sync...',1); setInterval(()=>{ console.log('sync...',2) },2000); console.log('sync...',3)
流程分析:
setInterVal
console.log('sync...',2)
setTimeout
&setInterval
)传递额外参数,可以使用polyfillclearInterval(timerId)
关闭指定定时器setInterval(code,delay)
,有安全风险。若是任务实际耗时超过delay,会出现同一时间触发多个回调。
有如下场景,每隔1s调用服务
// 时间间隔大于delay let count = 5 let intervalTimer = setInterval(function () { if (count <= 0) { clearInterval(intervalTimer) return } /*模拟延时任务*/ let timeoutTimer = setTimeout(function (count) { console.log(`the ${count} is running`) clearTimeout(timeoutTimer) }, Math.floor(Math.random() * (10000) + 1000),count) count-- }, 1000)
从上图可知,xhr响应没法按照顺序返回,这样就会致使没法正常处理结果
折中方案
function moreBetterInterval (count) { // 1s后调用 setTimeout(function (countDown) { console.log(count +' is begin') let timeoutTimer = setTimeout(function (times) { console.log(`the ${times} is running`) clearTimeout(timeoutTimer) times--; if(times>0){ moreBetterInterval(times) } }, Math.floor(Math.random() * (10000) + 1000),countDown) }, 1000,count) } moreBetterInterval(5)
能够保证递归以前已执行完回调,但没法保证按照必定的时间间隔。
let countDown=60; let timer=setInterval(function () { countDown--; if(countDown<0){ clearInterval(timer); countDown=60 } },1000)
setInterval(function () { let d = new Date() $('#clock')[0].innerHTML = d.toLocaleTimeString() }, 1000)
仅在Internet Explorer和Node.js下可用
做用:在循环事件任务完成后立刻运行指定代码
语法:setImmediate(func /**函数,必选*/,code /**表达式,可选*/,[ param1,param2,...]/**传递给函数的参数,可选*/)
;
setTimeout(func,0)
- 在HTML5中,若是是0,会根据嵌套层数初始化不小于4ms,各浏览器具体实现不一样
[](images/html.spec.whatwg_1.png)- 在Node.js中,若是是0,则初始化为1ms
谁先谁后,不必定~
须要考虑
做用:接受一个动画执行函数做为参数,这个函数的做用是仅执行一帧动画的渲染,并根据条件判断是否结束,若是动画没有结束,则继续调用requestAnimationFrame并将自身做为参数传入
语法:requestAnimationFrame(func /**函数,必选*/)
细节:以60FPS(每帧16.7ms)为目标,浏览器内部会选择渲染的最佳时机
setTimeout(func,16.7)
:容易卡顿缘由有两个:
- 实际执行时间晚于设定的延迟时间,出现卡顿
- 与浏览器刷新率有关,不一样设备的屏幕刷新频率可能会不一样,而setTimeout只能设定固定的时间间隔,没法保证与刷新率同步,容易丢帧
requestAnimationFrame
能节省CPU开销,当元素隐藏或不可见时,会中止渲染。而setTimeout仍在后台执行。cancelAnimationFrame(id)
关闭渲染动画经过以上定时器,最显著的共同点是:回调。
初一看,回调没有问题呀,能够延迟计算。请想下如下情景:
let msg = document.getElementById('msg') $('#btn').click(function (evt) { msg.innerHTML += `${new Date()} processing btn click callback... <br>` setTimeout(function request () { msg.innerHTML += `${new Date()} processing setTimeout callback...<br>` $.get('https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js', function (data, status) { msg.innerHTML += `${new Date()} processing ajax callback...<br>` }) }, 500) })
这里咱们用了三个函数嵌套,这种代码就被称为“回调地狱(callback hell)”,这样的代码难以编写,难以理解并且难以维护
$.get('https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js', function (data, status) { msg.innerHTML += `${new Date()} processing ajax callback...<br>` })
即本身程序的一部分的执行控制权交由某个第三方。在你不肯定这个回调可否按照预期执行时,发生意外时很难定位问题。
为了优雅的的处理回调最大的问题:控制反转,有如下方式:
error-first
风格-->Node.js中会将回调的第一个参数保留用做errorconst fs=require('fs') fs.readFile(__dirname,function(err,data) { if (err) console.log(err) //... })
但仍是不优雅,并无真正解决咱们的控制反转问题,只是将咱们以前担忧的程序异常暴露了出来。
可能如今你但愿有API或其余语言机制来解决这些问题。所幸,ES6会给你带来些干货~