es7 async和await ,作為genertor函數語法糖,在使用上比generator函數方便的,Generator 函數就是一個封裝的非同步任務,或者說是非同步任務的容器。非同步操作需要暫停的地方,都用yield語句註明. generator將非同步的流程標記的很簡潔,但是流程執行卻並不方便,所有 ...
es7 async和await ,作為genertor函數語法糖,在使用上比generator函數方便的,Generator 函數就是一個封裝的非同步任務,或者說是非同步任務的容器。非同步操作需要暫停的地方,都用yield
語句註明.
generator將非同步的流程標記的很簡潔,但是流程執行卻並不方便,所有我們需要藉助Generator的自執行下函數。Thunk 函數可以用於generator函數的自流程管理
async和await 作為generator的語法糖,自帶自執行器,相對於generator具有更好的語義,yield後面只能時promise,async,await 具有更好的適用性,並不明確規定是promise,async的返回的是promise
1.asycn和await的基本使用
async如果遇到await就會等待,等待其執行結果,才會往下繼續執行函數內部語句
/* 非同步執行方法 */ function timeout(ms) { return new Promise((res)=>{ console.log('settimeout') setTimeout(res,ms) }) } /* await 只能在async定義的函數內部使用 */ async function asyncpriint(value,ms) { timeout(ms); console.log(value); } asyncpriint('hello world',2000); // 先輸出settimeout等待2m鐘輸出hello world // 如果去掉await,輸出settimeout並且不等待直接輸出hello world
async函數返回的是一個promise
/* async返回時最終會轉成一個promise */ async function donow() { return 'czklove' } async function donow2 () { return new Promise(res=>{ res('czklove') }) } async function donow3 () { return Promise.resolve('czklove') } donow().then((val)=>{ console.log(val) }) // 輸出czklove donow2().then((val)=>{ console.log(val) }) // 輸出czklove /* 2和3是等價的,Promise.resolve 返回一個promise */ donow3().then((val)=>{ console.log(val) }) //輸出czklove // 輸出輸出czklove /* donow和donow2是等價的 也就是說返回值是一個值的話,他會自動轉化成promise */View Code
async返回的promise對象的狀態變化
/* resolve */ async function promiseresolve(){ await Promise.resolve('czkloveresolve') return 'czklove1' } /* rejuect */ async function promisereject(){ await Promise.reject('czkloverejuct') console.log(123) return 'czklove2' } /* 內部都是resolve 一直執行下去 */ promiseresolve().then(res=>{ console.log('resolve'+res) },rej=>{ console.log('reject'+rej) }) // resolveczklove1 /* 內部其中一個await是reject,則直接返回,不會再執行下去,並且返回值是rejuect的值 */ promisereject().then(res=>{ console.log('resolve'+res) },rej=>{ console.log('reject'+rej) }) // 不會執行console.log(123) // rejectczkloverejuct
await 命令後面是一個promise對象,返回該對象的結果,如果不是promise,值直接放回該值
如果後面是一個帶有then 方法的對象,那麼會將其等同於promise
await 後面的promise如果執行了rejuect 則整個函數終止,並且返回該對象的結果,返回的promise對象的狀態也是rejuect的
如果我們想繼續執行下去,則可以將reject的promise 放入try catch 模塊中,另外一種是後面跟.catch 方法
/* 定義一個async 函數 */ async function awaitfc() { try { /* 放入try 和 catch 中 reject 不會終止函數執行 */ await Promise.reject('czklove') } catch (e){ } /* .catch 也可以使 reject 不會終止函數執行*/ await Promise.reject('czklove').catch((e)=>{ console.log(e) }) return 'jgczklove' } awaitfc().then(val=>{ console.log(val) }) //czklove async.jsView Code
函數的併發執行或繼發執行
/* 定義一個async 函數 */ let i = 1; function settime(ms) { return new Promise((res)=>{ setTimeout(()=>{ res ('123'+(i++)) },ms) }) } /* 繼發執行 */ async function funa() { let val1 = await settime(2000) console.log(val1) let val2 = await settime(2000) console.log(val2) let val3 = await settime(2000) console.log(val3) console.log('1111') } /* 併發執行 */ async function funa2() { let val1 = settime(2000); let val2 = settime(3000); let val3 = settime(2000); console.log(await val1) console.log(await val2) console.log(await val3) console.log(2222) } funa(); /* 繼發執行 結果是順序的 每隔2秒 輸出1231 1232 1233 ,最終輸出1111 */ funa2(); /* 併發 val1 val2 val3 輸出結果順序是不定的,但是可以確認,最終才輸出2222 */
使用promise.all 也可以達到併發執行