摘要:結果輸出可以看出函數返回的是一個對象,如果函數中一個直接量,函數會封裝成對象返回,而如果沒有返回值時,函數會返回在沒有結合時,函數會立即執行,返回一個對象。
JS中的異步操作從最初的回調函數演進到Promise,再到Generator,都是逐步的改進,而async函數的出現仿佛看到了異步方案的終點,用同步的方式寫異步。
原文鏈接
async函數簡單解釋async函數就是Generator函數的語法糖。
Generator函數寫法
let promise = function (val){ return new Promise(function (resolve, reject){ setTimeout(()=>{ console.log(val); resolve(val); },1000); }); }; let gen = function* (){ let p1 = yield promise("1"); let p2 = yield promise("2"); }; let genF = gen();
async函數寫法
let promise = function (val){ return new Promise(function (resolve, reject){ setTimeout(()=>{ console.log(val); resolve(val); },1000); }); }; let gen = async function (){ let p1 = await promise("1"); let p2 = await promise("2"); };
async函數是在Generator函數上進行的改進,語法上Generator函數的星號換成了async,yield換成了await。
而async也與Generator函數不同:
自帶內置執行器,Generator函數需要依靠執行器,而async可以和普通函數一樣,只需要一行
相對Generator函數,async和await語義更清楚
適用性強,yield后只能是Thunk函數和Promise對象,而await后可以是Promise對象和原始類型的值(數值、字符串、布爾型等)
async作用寄予async函數的期望是希望可以幫助我們解決異步操作問題,所以需要搞清楚async函數的返回值是什么。
async function asyncAwait() { return "async await"; } let a = asyncAwait(); console.log(a);
結果輸出:
Promise {: "async await"}
可以看出async函數返回的是一個Promise對象,如果函數中return一個直接量,async函數會封裝成Promise對象返回,而如果沒有返回值時,async函數會返回undefined
Promise {: undefined}
在沒有結合await時,async函數會立即執行,返回一個Promise對象。
await等待await是個運算符,等待的結果是Promise對象或其他值,比如:
function func1() { return "async"; } async function func2() { return Promise.resolve("await"); } async function asyncAwait() { let f1 = await func1(); let f2 = await func2(); console.log(f1, f2); } asyncAwait()
結果輸出:
async await
await表達式的運算取決于等待的結果,如果它等到的不是一個Promise對象,那運算結果就是它等到的東西,
而如果它等到的是一個Promise對象,它會阻塞后面的代碼,等著Promise對象resolve,然后得到resolve的值,作為表達式的運算結果。
async函數調用會封裝在Promise中,這也是await需要在async函數中使用的原因。
對于多個異步操作中,Promise的then可以解決多層回調問題。
function ajax(t) { return new Promise(resolve => { setTimeout(() => resolve(t + 200), t); }); } function step1(t) { console.log(`step1 in ${t}ms`); return ajax(t); } function step2(t) { console.log(`step2 in ${t}ms`); return ajax(t); } function step3(t) { console.log(`step3 in ${t}ms`); return ajax(t); } function submit(){ console.time("submit"); step1(200) .then(time2 => step2(time2)) .then(time3 => step3(time3)) .then(result => { console.log(`result is ${result}ms`); console.timeEnd("submit"); }); } submit();
async函數實現:
function ajax(t) { return new Promise(resolve => { setTimeout(() => resolve(t + 200), t); }); } function step1(t) { console.log(`step1 in ${t}ms`); return ajax(t); } function step2(t) { console.log(`step2 in ${t}ms`); return ajax(t); } function step3(t) { console.log(`step3 in ${t}ms`); return ajax(t); } async function submit(){ console.time("submit"); const t1 = 200; const t2 = await step1(t1); const t3 = await step2(t2); const result = await step3(t3); console.log(`result is ${result}`); console.timeEnd("submit"); } submit();
結果輸出:
step1 in 200ms step2 in 400ms step3 in 600ms result is 800 submit: 1209.85107421875ms
而如果需求變更,每一步的參數都是之前步驟的結果后,async函數可以寫成:
function ajax(t) { return new Promise(resolve => { setTimeout(() => resolve(t + 200), t); }); } function step1(t1) { console.log(`step1 in ${t1}ms`); return ajax(t1); } function step2(t1, t2) { console.log(`step2 in ${t1}ms,${t2}ms`); return ajax(t1 + t2); } function step3(t1, t2, t3) { console.log(`step3 in ${t1}ms,${t2}ms,${t3}ms`); return ajax(t1 + t2 + t3); } async function submit(){ console.time("submit"); const t1 = 200; const t2 = await step1(t1); const t3 = await step2(t1, t2); const result = await step3(t1, t2, t3); console.log(`result is ${result}`); console.timeEnd("submit"); } submit();
結果輸出:
step1 in 200ms step2 in 200ms,400ms step3 in 200ms,400ms,800ms result is 1600 submit: 2210.47998046875msasync/await注意點
async用來申明里面包裹的內容可以進行同步的方式執行,await則是進行執行順序控制,每次執行一個await,阻塞代碼執行等待await返回值,然后再執行之后的await。
await后面調用的函數需要返回一個promise。
await只能用在async函數之中,用在普通函數中會報錯。
await命令后面的Promise對象,運行結果可能是rejected,所以最好把await命令放在try...catch代碼塊中。
async/await try/catch寫法async function asyncAwait() { try { await promise(); } catch (err) { console.log(err); } } // 另一種寫法 async function asyncAwait() { await promise().catch(function (err){ console.log(err); }); }總結
async/await是ES7的重要特性之一,也是目前社區里公認的優秀異步解決方案,當你深入了解原理后會發現仿佛看到了異步回調隧道的盡頭亮光。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/107304.html
摘要:以往的異步方法無外乎回調函數和。當然,對這個新特性也有一定的擔心,體現在他使得異步代碼變的不再明顯,我們好不容易已經學會并習慣了使用回調函數或者來處理異步。 自從Node的7.6版本,已經默認支持async/await特性了。如果你還沒有使用過他,或者對他的用法不太了解,這篇文章會告訴你為什么這個特性不容錯過。本文輔以大量實例,相信你能很輕松的看懂,并了解Javascript處理異步的...
摘要:以往的異步方法無外乎回調函數和。當然,對這個新特性也有一定的擔心,體現在他使得異步代碼變的不再明顯,我們好不容易已經學會并習慣了使用回調函數或者來處理異步。 自從Node的7.6版本,已經默認支持async/await特性了。如果你還沒有使用過他,或者對他的用法不太了解,這篇文章會告訴你為什么這個特性不容錯過。本文輔以大量實例,相信你能很輕松的看懂,并了解Javascript處理異步的...
摘要:以往的異步方法無外乎回調函數和。出錯了出錯了總結接口遍歷器對象除了具有方法,還可以具有方法和方法。函數調用函數,返回一個遍歷器對象,代表函數的內部指針。 引言 接觸過Ajax請求的會遇到過異步調用的問題,為了保證調用順序的正確性,一般我們會在回調函數中調用,也有用到一些新的解決方案如Promise相關的技術。 在異步編程中,還有一種常用的解決方案,它就是Generator生成器函數。顧...
摘要:回調函數,一般在同步情境下是最后執行的,而在異步情境下有可能不執行,因為事件沒有被觸發或者條件不滿足。同步方式請求異步同步請求當請求開始發送時,瀏覽器事件線程通知主線程,讓線程發送數據請求,主線程收到 一直以來都知道JavaScript是一門單線程語言,在筆試過程中不斷的遇到一些輸出結果的問題,考量的是對異步編程掌握情況。一般被問到異步的時候腦子里第一反應就是Ajax,setTimse...
閱讀 813·2021-11-18 10:02
閱讀 2503·2021-11-11 16:54
閱讀 2750·2021-09-02 09:45
閱讀 654·2019-08-30 12:52
閱讀 2774·2019-08-29 14:04
閱讀 2745·2019-08-29 12:39
閱讀 448·2019-08-29 12:27
閱讀 1887·2019-08-26 13:23