同步: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會給你帶來些乾貨~