在以前咱們處理異步函數都是用回調這個方法,回調嵌套的時候會發現 閱讀性 和 調試 的難度會增長不少;
想象一下,你把一個任務交給一個不錯的小夥子,他叫承諾;不用擔憂你交給他的任務會丟失,他總會返回的,作成功了resolve,失敗了reject;node
var promise = new Promise((resolve, reject) =>{ //交給給「承諾」同窗一個異步任務 setTimeout(()=>{ if(true){ // 成功了,返回params resolve('params') }else{ // 失敗了,返回error reject('error') } }, 1000) }) // 上面是給承諾一個任務,下面是"承諾"同窗的返回 promise.then((res)=>{ console.log(res) }).catch((rej)=>{ console.log(res) })
實際狀況中,異步的場景沒有那麼簡單,你能夠會遇到下面這些場景git
let promise = new Promise((res, rej)=>{ asyncFunc('promise', 1000, res, rej) }) promise.then(res=>{ console.log(res); return new Promise((res, rej)=>{ asyncFunc('second', 2000, res, rej) }) }).then(res=>{ console.log(res); return new Promise((res, rej)=>{ asyncFunc('third', 1000, res, rej) }) // throw 'oh, no!'; }).then(res=>{ console.log(res); console.log('endinggggggg') }).catch(err=>{ console.log('catch', err) })
let promise1 = new Promise((res, rej)=>{ asyncFunc('promise1', 1000, res, rej) }) let promise2 = new Promise((res, rej)=>{ asyncFunc('promise2', 2000, res, rej) }) let promise3 = new Promise((res, rej)=>{ asyncFunc('promise3', 1000, res, rej) }) var promiseAll = Promise.all([promise1, promise2, promise3]) promiseAll.then(res =>{ console.log('最終的結果', res) }).catch(err =>{ console.log('catch', err); })
let promise1 = new Promise((res, rej)=>{ asyncFunc('promise1', 1000, res, rej, true) }) let promise2 = new Promise((res, rej)=>{ asyncFunc('promise2', 2000, res, rej, true) }) let promise3 = new Promise((res, rej)=>{ asyncFunc('promise3', 1000, res, rej) }) // 1000s的任務完成了,就直接返回promise1了 var promiseRace = Promise.race([promise1, promise2, promise3]) promiseRace.then(res =>{ console.log('最終的結果', res) }).catch(err =>{ console.log('catch', err); })
講這一塊的東西就得講講nodejs的事件處理機制;
事件隊列應該是一個數據結構,全部的事情都被事件循環排隊和處理,直到隊列爲空。可是Node中的這種狀況與抽象反應器模式如何描述徹底不一樣。
下面講的東西只適合V8;
NodeJS中有許多隊列,其中不一樣類型的事件在本身的隊列中排隊。github
在處理一個階段以後而且在移到下一個隊列以前,事件循環將處理兩個中間隊列,直到中間隊列中沒有剩餘的項目。web
有四種主要類型,由libuv事件循環處理;promise
還有2箇中間隊列,不屬於libuv自己的一部分,可是是nodejs的一部分;安全
上圖是node中libuv模塊在處理異步I/O操做的流程圖; 數據結構
Node經過定時器檢查隊列中的任何過時定時器來啓動事件循環,並在每個步驟中遍歷每個隊列。若是沒有任務則循環退出,每一次隊列處理都被視爲事件循環的一個階段。特別有意思的是中間紅色的隊列,每次階段都會優先去處理中間隊列的任務。而後再去處理其餘的隊列。異步
async/await 能夠是Generator和promise結合實現的;
實際狀況中,異步的場景沒有那麼簡單,你能夠會遇到下面這些場景
const delay = timeout => new Promise(resolve => setTimeout(resolve, timeout)); async function f(){ await delay(1000); await delay(2000); await delay(3000); return 'done' } f().then(v=> console.log(v));
let a; async function g(){ await Promise.reject('error'); a = await 1; } g().then(v=>console.log(v)).catch(err=>console.log(err));
let a ; async function g(){ try{ await Promise.reject('error') }catch(err){ console.log(err) } a= await 1; return a; } g().then(v=>console.log(v)).catch(err=>console.log(err));
async function series(){ const await1 = delay(1000); const await2 = delay(1000); await await1; await await2; return 'done' } series();
若是有不對的能夠提issue
若是以爲對你有幫助能夠star下
githubasync
https://juejin.im/post/5b777f...ide
https://jsblog.insiderattack....