在以前咱们处理异步函数都是用回调这个方法,回调嵌套的时候会发现 阅读性 和 调试 的难度会增长不少;
想象一下,你把一个任务交给一个不错的小伙子,他叫承诺;不用担忧你交给他的任务会丢失,他总会返回的,作成功了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....