理解ES7中的async/awaitpromise
优点是:就是解决多层异步回调的嵌套异步
从字面上理解 async/await, async是 "异步"的含义,await能够认为是 async wait的简写,所以能够理解 async 用于声明一个function是异步的,而await用于等待一个异步方法执行完成返回的值(返回值能够是一个Promise对象或普通返回的值)。
注意:await 只能出如今 async函数中。async
1-1 async的做用?
首先来理解async函数是怎么处理返回值的,咱们之前写代码都是经过return语句返回咱们想要的值,可是async与return有什么区别呢? 下面咱们看以下代码:函数
async function testAsync() { return 'hello world'; } const result = testAsync(); console.log(result); // 打印出来看到 返回一个promise对象
如上代码,咱们输出的是一个Promise对象。所以 async返回的是一个Promise对象,所以咱们可使用 then()链来处理这个Promise对象。像以下代码:优化
async function testAsync() { return 'hello world'; } const result = testAsync(); result.then(v => { console.log(v); // 输出 hello world });
可是若是 async函数没有返回值的话,那么就会返回 undefined; 以下代码:spa
async function testAsync() { return; } const result = testAsync(); result.then(v => { console.log(v); // 输出 undefined });
1-2 await的做用?
从语义上说,await是在等待一个async函数完成的,async函数返回的是一个Promise对象,await等待的是一个表达式,这个表达式的计算结果是Promise对象或其余值。
async函数返回一个Promise对象,await做用是用于等待一个async函数的返回值。
await函数后面能够接普通函数调用或直接量,请看以下代码:code
function getSomething() { return 'something'; } async function testAsync() { return Promise.resolve('hello'); } async function test () { const v1 = await getSomething(); const v2 = await testAsync(); console.log(v1); // something console.log(v2); // hello } test();
注意:await 是等待async函数返回的Promise对象或其余值,await是一个运算符,用于组成表达式, 若是等待的是一个Promise对象,await会阻塞后面的代码(async调用不会形成堵塞,它内部全部的堵塞
都被封装在一个Promise对象中异步执行),等待Promise对象的resolve,而后获得resolve的值,做为await表达式的运输结果。对象
1-3 async/await 的一块儿使用的做用及优点在哪?
咱们先不用 async/await, 来看看使用setTimeout模拟异步操做以下代码:blog
var test = function(time) { return new Promise((resolve, reject) => { setTimeout(function(){ resolve('hello world'); }, time) }); }; test(1000).then((v) => { console.log(v); });
若是改用 async/await 代码以下:get
var testAsync = function(time) { return new Promise((resolve, reject) => { setTimeout(function(){ resolve('hello world'); }, time) }); }; async function test(time) { const v = await testAsync(time); console.log(v); // hello world } test(1000);
看上面的代码,反而会以为 使用 async/await 代码变得多一点,复杂一点,可是结果貌似都同样,那么使用 async/await的优点在哪?
1-4 async/await的优点在于处理then链
单一的Promise链貌似不能发现 async/await的优点,可是若是须要处理多个Promise组成的then链的时候,优点能够看出来,由于Promise是经过then链来解决多层回调的问题,如今咱们又可使用
async/await来进一步优化,他们的优势就是解决多层异步回调的嵌套。
假设咱们如今有一个需求是,分多个步骤完成,每一个步骤都是异步的,而且后面的异步都须要依赖于上一个异步回调返回的数据,进行往下传递。咱们先用 setTimeout来模拟异步操做。
function useTimeout (t) { return new Promise((resolve, reject) => { setTimeout(()=> { resolve(t+100) }, t); }); } function step1(t) { console.log(`step1 with ${t}`); // step1 with 300 return useTimeout(t); } function step2(t) { console.log(`step2 with ${t}`); // step2 with 400 return useTimeout(t); } function step3(t) { console.log(`step3 with ${t}`); // step3 with 500 return useTimeout(t); } function test() { const time1 = 300; step1(time1) .then(time2 => step2(time2)) .then(time3 => step3(time3)) .then(res => { console.log(`result is ${res}`); // result is 600 }) } test();
若是咱们使用 async/await来实现,代码变为以下:
function useTimeout (t) { return new Promise((resolve, reject) => { setTimeout(()=> { resolve(t+100) }, t); }); } function step1(t) { console.log(`step1 with ${t}`); // step1 with 300 return useTimeout(t); } function step2(t) { console.log(`step2 with ${t}`); // step2 with 400 return useTimeout(t); } function step3(t) { console.log(`step3 with ${t}`); // step3 with 500 return useTimeout(t); } async function test() { const time1 = 300; const time2 = await step1(time1); const time3 = await step2(time2); const result = await step3(time3); console.log(`result is ${result}`); } test();
上面咱们能够看到 使用async/await 代码看起来都是同步的,等第一步完成后,再执行第二步,依次类推..... 而且不须要更多的回调函数嵌套。
下面咱们再来看下咱们以前讲的,后面的步骤须要上一个步骤的结果传递进去,使用async/await的优点可能更明显。
以下代码:
function useTimeout (t) { return new Promise((resolve, reject) => { setTimeout(()=> { resolve(t+100) }, t); }); } function step1(t1) { console.log(`step1 with ${t1}`); // step1 with 300 return useTimeout(t1); } function step2(t1, t2) { console.log(`step2 with ${t1} and ${t2}`); // step2 with 300 and 400 return useTimeout(t1+t2); } function step3(t1, t2, t3) { console.log(`step3 with ${t1} and ${t2} and ${t3}`); // step3 with 300 and 400 and 800 return useTimeout(t1+t2+t3); } async function test() { const time1 = 300; const time2 = await step1(time1); const time3 = await step2(time1, time2); const result = await step3(time1, time2, time3); console.log(`result is ${result}`); // result is 1600 } test();
1-5 捕捉错误
咱们可使用 try catch 来捕获错误,以下代码:
var sleep = function (time) { return new Promise((resolve, reject) => { setTimeout(function() { // 出错了, 返回 error reject('error'); }, time); }) }; var start = async function() { try { console.log('start'); await sleep(3000); // 返回一个错误 // 下面代码不会被执行 console.log('end'); } catch (err) { console.log(err); // 捕捉错误 error } }; start();