【Web前端基础知识】如何利用promise解决异步

发布 : Web前端培训      来源:优就业

2021-09-28 14:16:38

我们知道,在promise对象的then方法可以处理onfulfilled和onrejected两个事件监听回调,但是我们一般采用catch来处理onrejected的监听回调,因为catch可以捕获部分程序异常;有利于程序的健壮性。例如:

  1. function getBanner() {
  2. let p = new Promise((resolve, reject) => {
  3. $.ajax({
  4. type: "GET",
  5. url: "http://localhost:3000/api/index/banner",
  6. success: function (response) {
  7. resolve(response);
  8. },
  9. error: function (err) {
  10. reject(err);
  11. }
  12. });
  13. });
  14. return p;
  15. }
  16. let p = getBanner()
  17. .then(rst => {
  18. return rst;
  19. })
  20. .catch(err => {
  21. console.log(err);
  22. });

我们通过jQuery的ajax来向服务器发起轮播图数据的请求,上面代码若是正确的执行则会进入then方法里处理,若是异常的,也就是说必然进入catch环节,这代码看起来并没有什么,好像也并不复杂。

但是,如果在异步请求过程中出现了几个请求直接有依赖关系,则使用这种解决方案就复杂得多了。例如:

  1. $.ajax({
  2. url: "http://www.ujiuye.tech/:3000/api/firstCategory", // 所有一级分类
  3. dataType: "json",
  4. success(res) {
  5. $.ajax({
  6. url: `http://www.ujiuye.tech/:3000/api/secondCategory`, // 传递一级ID换取下属的二级分类列表
  7. data: {
  8. firstId: res['list'][0][0]['firstId']
  9. },
  10. dataType: "json",
  11. success(res2) {
  12. $.ajax({
  13. url: `http://www.ujiuye.tech/:3000/api/thiredCategory`, // 传递二级分类ID, 获取下属的三级分类列表
  14. data: {
  15. secondId: res2['list'][0]['secondId']
  16. },
  17. dataType: "json",
  18. success(res3) {
  19. $.ajax({
  20. url: `http://www.ujiuye.tech/:3000/api/categoryList`,// 传递三级分类ID, 获取下属的商品数据列表
  21. data: {
  22. thiredId: res3['list'][0]['thiredId']
  23. },
  24. dataType: "json",
  25. success(result) {
  26. console.log(result);
  27. }
  28. })
  29. }
  30. })
  31. }
  32. })
  33. }
  34. })

在小U商城项目中的商品列表页面,我们同时要发起四个请求来分别获取:一级分类、二级分类、三级分类和商品,那么这是时候利用回调函数会出现”回调地狱”的现象,即使是使用promise来优化,也会出现大量的代码嵌套,这样的代码会容易让人疑惑,而且也不利于后续的开发维护。所以我们可以使用async...await来优化这些。

例如上面请求轮播图的例子,使用async和await来优化之后:

  1. function getBanner() {
  2. let p = new Promise((resolve, reject) => {
  3. $.ajax({
  4. type: "GET",
  5. url:
  1. "http://localhost:3000/api/index/banner",
  2. success: function (response) {
  3. resolve(response);
  4. },
  5. error: function (err) {
  6. reject(err);
  7. }
  8. });
  9. });
  10. return p;
  11. }
  12. async function getData(){
  13. let data=await getBanner();
  14. console.log(data);
  15. }

这样的代码相比于上面的代码要简化很多,但是也有弊端,由于await只能接收promise的成功结果,也就是说,若上面代码出现了异常,则代码会中断执行。作为一个优秀的开发人员肯定不希望代码崩掉,那么该如何解决异常呢,有两种方案:一是采用try..catch来捕获异常,另外是使用catch

  1. async function getData() {
  2. try {
  3. let data = await getBanner();
  4. console.log(data);
  5. } catch (e) {
  6. console.log(e);
  7. }
  8. }
  9. //或者
  10. async function getData() {
  11. let data = await getBanner().catch(e => {
  12. console.log(e);
  13. })
  14. console.log(data);
  15. }

但这两种方案都又会出现嵌套,特别是若发起一些负责的请求(例如上面回调地狱的情况),则代码依然非常复杂,那么有没有更好的解决方案呢。答案是有。在项目开发过程中,我们经常使用await-to-js的技术来解决这个问题:

  1. function to(p) {
  2. return p
  3. .then(data => [null, data])
  4. .catch(err => [err, null]);
  5. }

其实这个方案依然是利用promise的链式调用原理来解决的。那么使用,最后代码为:

  1. function to(p) {
  2. return p
  3. .then(data => [null, data])
  4. .catch(err => [err, null]);
  5. }
  6. async function getData() {
  7. let [err, data] = await to(getBanner())
  8. }

利用这个方案,大家发现,代码量不仅大大的减少,而且兼容性更加友好。

THE END  

声明:本站稿件版权均属中公教育优就业所有,未经许可不得擅自转载。

领取零基础自学IT资源

涉及方向有Java、Web前端、UI设计、软件测试、python等科目,内容包含学习路线、视频、源码等

点击申请领取资料

点击查看资料详情 

收起 


 相关推荐

问题解答专区
返回顶部