今天状态不太好,睡久了懵一天。
以前只是了解过async函数,并还没有很熟练的运用过,所以先开个坑吧,以后再结合实际来更新下,可能说的有些问题希望大家指出。
async和await相信大家应该不陌生,让异步处理变得更友好。
其实这玩意儿就是个Generator的语法糖,想深入学习得去看看Generator,不然你可能只停留在会用的阶段。
用法很简单,看代码吧。
// 先声明一个函数,这个函数返回一个promise, 先记住哈!后面很多地方要用 function getPromise(str = 'sucess') { return new Promise((resolve) => { setTimeout(() => resolve(str), 1000); }); } // async表示,这个函数有异步操作! async function fn() { // getPromise会返回一个Promise const data = await getPromise(); // fn运行在这停顿,这里会停1秒,最后输出data // 要wait等待getPromise()这个异步操作返回结果 console.log(data, 'data'); // 最后返回data,当然你要是处理完业务也可以不返回 // 视场景而定了,只是想告诉你async会返回一个promise,而这个data在then里面拿到 return data; } fn().then(res => console.log(res) 'res'); // 这段代码运行出来两个sucess
我觉得async最大的好处就是,代码结构更清晰,有更好的语义,写复杂业务的时候阅读起来更快更爽。
接下来模拟一个实际项目的业务场景来看看用法区别
业务场景:我们有一本书,目前只有书名
要通过请求 getBookId 获取到书的id
然后靠id通过请求 getBookDes 获取到书的description
最后要把id,和title,还有description一起存到数据库中 uploadBookInfo
不要纠结http请求如何封装哈,这里我直接给几个模拟例子让同学们方便试,
// 获取书籍Id function getBookId() { return new Promise((resolve) => { setTimeout(() => resolve('1001'), 1000); }); } // 获取书籍描述 function getBookDes() { return new Promise((resolve) => { setTimeout(() => resolve('这是一本好书'), 1000); }); } // 上传书籍信息 function uploadBookInfo() { return new Promise((resolve) => { setTimeout(() => resolve('上传成功'), 1000); }); } // promise写法 function uploadWidthPromise(title = '你不知道的java script') { this.getBookId(title).then((id) => { console.log(id); // 1001 this.getBookDes(id).then((des) => { console.log(des); // 这是一本好书 this.uploadBookInfo({ title, id, des, }).then((res) => { console.log(res); // 上传成功 }); }); }); } // async写法 async function uploadWidthAsync(title = '你不知道的java script') { const id = await this.getBookId(title); const des = await this.getBookDes(id); const result = await this.uploadBookInfo({ id, des, title }); console.log(id, des, result); // 1001 这是一本好书 上传成功 },
这明显的差距啊,以前用回调,后来用promise觉得这个then可真好用啊,异步完了我就then里面接着写,多清晰!
现在有了await,真香!
而且用await你会发现你的代码执行下来,看起来就像是由上往下执行的顺序,一眼就看完这些干了啥。
接下来要说几点用async函数过程中要注意的东西
划重点啦!!
1. 错误捕捉
await语句后面跟着的promise对象一旦抛出错误,也就是变成reject状态,那么整个async函数就会停止执行抛出错误。
什么意思呢?
async function thorwErr() { await Promise.reject('出错'); console.log('执行了吗?'); // 不会执行,以下代码都不会执行 return await Promise.resolve('成功'); }, thorwErr().then((res) => { console.log(res); // 成功,并不会弹出,因为第一句awiat已经抛错,被下面的catch捕获,而且async直接停止执行 }).catch((err) => { console.log(err); // 出错 }); // 最后只会输出两个字 出错
那么这种情况有时候是不符合业务逻辑的,如果我们希望第一句即使出错也不会中断,那么我们需要用到一个try ... catch,如下
async function thorwErr() { try { await Promise.reject('出错'); } catch(err) { console.log(err); // 出错 } console.log('执行了吗?'); return await Promise.resolve('成功'); },
这样写就会被try...catch捕获错误,而不会被async的catch捕获造成函数停止执行
最后输出的也是 出错 执行了吗 成功 这样的三句话
当然也可以换种方式写,如下
async function thorwErr() { await Promise.reject('出错').catch(err => console.log(err)); console.log('执行了吗?'); return await Promise.resolve('成功'); }
这样写也ok,道理是一个道理。错误内部直接处理了,不抛给async函数。
在看 阮一峰的ES6 的时候还看到一个例子,我觉得不错分享给大家。
实现了一个多次尝试请求,也许会有这种情景,一个第三方接口不太稳定,可能要多次调用才会成功一次,就可以用这种方案解决
const limit_num = 3; // 限制次数 3次