js中的異步 使用像 JavaScript 這樣的語言編程時,很重要但經常被誤解的一點是,如何表達和控制持續一段時間的程序行爲。 如從數據庫或文件系統中請求數據而後顯示數據、經過網絡發送數據並等待響應,或者是在以固定時間間隔執行重複任務(好比動畫)等。這些程序並不會以及運行結束,一般一部分運行在當下,另外一部分運行在未來。 事實上,程序中如今運行的部分和未來運行的部分之間的關係就是異步編程的核心。 ---------------------<你不知道的Javascript> 回調函數 首先要鬧明白兩個問題: 問題一:什麼是回調函數? 答:函數A中傳入函數B做爲參數時,函數B即爲A函數執行的回調函數。(設計JavaScript中傳值調用,函數可做爲值傳遞等知識點) 問題二:回調函數都是異步嗎? 由回調函數定義可推導,並不是全是異步。 //非異步 const arr = [1,2,3] const cb =item => { console.log(item) } //callback arr.map(cb) //異步 setTimeout(()=>{ console.log('setTimeout')},0) 一段代碼開始: //分析以下代碼輸出 console.log('start') setTimeout( function(){ console.log('setTimeOut') }, 1000 ); console.log('end') // start -> end -> setTimeout 以上代碼可抽象出兩個問題: 1、代碼的執行順序非線性(定義順序與執行順序不一致) 2、回調函數執行強依賴於宿主環境(setTimeout函數不是javascript自帶方法,相似有fs.readFile),致使信任問題 對於第一個問題,隨着代碼量增長,理解代碼自己的難度會劇增。如 listen( "click", function handler(evt){ setTimeout( function request(){ ajax( "http://some.url.1", function response(text){ if (text == "hello") { handler(); } else if (text == "world") { request(); } }); }, 500) ; });
當咱們回顧項目,看到這一段代碼時,咱們的眼球會在各個事件及其對應的回調之間週轉,未必能當即理解該代碼所表示的含義。 咱們大腦中的邏輯爲: A、當前,添加click事件監聽函數 B、將來(觸發click事件), 調用setTimeout C、將來的將來(500ms定時觸發),調用request D、最遠的將來(ajax請求返回),判斷返回值 這時候感慨一聲:若是代碼能像A、B、C、D同樣簡潔那該多好! 對於第二個問題,作詳細詮釋: 1、怎麼理解這裏說的信任問題? const cb = ()=>{console.log('可信任?')} setTimeout(cb,1000) cb只執行一次嗎? 可能這裏使用了標準化的setTimeout方法,你會說yes,固然只執行一次。那麼,若是你使用的是第三方庫呢? 也許能夠這樣解決 let trust = false const cb = ()=>{ if(!trust){trust = true} console.log('可信任?') } setTimeout(cb,1000) 那麼, • 調用cb過早(在追蹤以前); • 調用cb過晚(或沒有調用); • 調用cb的次數太少或太多; • 沒有把所需的環境 / 參數成功傳給你的回調函數; • 吞掉可能出現的錯誤或異常; 呢? 2、如何解決信任問題? 信任問題產生的根源在於,雖然由咱們本身定義回調函數,但回調函數的執行卻依賴於第三方。 解決這個問題,就必須在javascript中內置異步處理模式,promise粉末登場