async 函数概述
async/await应该是目前最简单的异步方案,ES7 中新增了 async/await 两个关键词。
async 可以声明一个异步函数,此函数需要返回一个 Promise 对象。await 可以等待一个 Promise 对象 resolve,并拿到结果。
其实async函数是对 Generator 函数的改进,同步表达异步操作,真正意义上解决异步回调的问题
语法结构
async function foo() { await 异步操作; await 异步操作; }
async 函数基本用法
async函数返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
async 表示这是一个async函数,await只能用在这个函数里面。
await 表示在这里等待promise返回结果了,再继续执行。
await 后面跟着的应该是一个promise对象(当然,其他返回值也没关系,只是不会等待结果的返回会立即执行,如果这样的话,async函数就没有意义了)
var sleep = function (time) { return new Promise(function (resolve, reject) { console.log('执行'); setTimeout(function () { resolve(); }, time); }); }; var start = async function () { // 在这里使用起来就像同步代码那样直观 console.log('start'); await sleep(3000); console.log('end'); }; start(); // 执行结果是start 执行 end
得到promise对象的返回值——await等待的虽然是promise对象,但不必写.then(..),直接可以得到返回值
var sleep = function (time) { return new Promise(function (resolve, reject) { console.log('执行'); setTimeout(function () { resolve('ok'); // 返回 ‘ok’ }, time); }); }; var start = async function () { // 在这里使用起来就像同步代码那样直观 console.log('start'); let result = await sleep(3000); console.log(result); console.log('end'); }; start();
捕捉promise的错误——既然.then(..)不用写了,那么.catch(..)也不用写,可以直接用标准的try catch语法捕捉错误
var sleep = function (time) { return new Promise(function (resolve, reject) { console.log('执行'); setTimeout(function () { reject('出错了'); // 返回错误信息 ‘出错了’ }, time); }); }; var start = async function () { // 在这里使用起来就像同步代码那样直观 console.log('start'); await sleep(3000).catch(function (result) { console.log(result); }); console.log('end'); }; start();
使用这种catch()的方式,后面的程序还可以继续执行,如果使用下面这种方式的话,被try下面的程序不会继续执行
var sleep = function (time) { return new Promise(function (resolve, reject) { console.log('执行'); setTimeout(function () { reject('出错了'); // 返回错误信息 ‘出错了’ }, time); }); }; var start = async function () { try { console.log('start'); await sleep(3000); // 这里得到了一个返回错误 // 所以以下代码不会被执行了 console.log('end'); } catch (err) { console.log(err); // 这里捕捉到错误信息 `出错了` } }; start();
循环多个await——await看起来就像是同步代码,所以可以理所当然的写在for循环里,不必担心以往需要闭包才能解决的问题 值得注意的是,await必须在async函数的上下文中的
var sleep = function (time) { return new Promise(function (resolve, reject) { console.log('执行'); setTimeout(function () { resolve('ok'); }, time); }); }; var start = async function () { try { console.log('start'); for (var i = 1; i <= 5; i++) { console.log(`当前是第${i}次等待..`); console.log(await sleep(1000)); } console.log('end'); } catch (err) { console.log(err); } }; start();
await只能在async函数中运行——下面依次是错误的代码和正确的代码
var sleep = function (time) { return new Promise(function (resolve, reject) { console.log('执行'); setTimeout(function () { resolve('ok'); }, time); }); }; var start = async function () { try { var arr = [1,2,3,4,5] console.log('start'); for(var v of arr) { console.log(`当前是第${v}次等待..`); console.log(await sleep(1000)); // 正确, for循环的上下文还在async函数中 } console.log('end'); } catch (err) { console.log(err); } }; start();