简述

在平时coding中,有时可能会遇到某些业务场景需要在同一时间只能做一件事,做完了才能做下一件事情。这种很明显符合同步操作的逻辑,但如果不采取某些优雅的编程方式可能就会导致如图这样的结果,很有可能就会产生传说中的回调地狱
mmexport1630667579527.jpg

需求

假设现在有这样一个场景,我们需要去爬取一个网站上的数据,需要先将大致内容爬取下来,再逐步去筛选小部分的内容,再根据小部分的内容去获取具体的资源。如何利用**Promise**去实现这个需求呢?

1. Promise写法

  1. //模拟需要进行的操作
  2. let option = ["爬取音乐列表api", "爬取单曲id", "根据单曲id爬取具体资源"];
  3. //定义一个通用的请求数据的方法
  4. function getData(option) {
  5. return new Promise((resolve, reject) => {
  6. //利用setTimeout模拟真实网络中的请求速度
  7. setTimeout(() => {
  8. //真实情况Promise里返回的是通过异步请求得到的网络数据,这里暂且用文字提示
  9. resolve("success: " + option);
  10. }, 1000);
  11. })
  12. }

现在就需要我们进行一步又一步地操作了…

执行getData()函数,由于这个函数返回的是Promise对象,所以可以利用.then()方法来接收,在.then()方法中对返回的数据进行处理以后,又在.then()方法中执行getData()函数,getData()函数中传入下一步要操作的内容。以此类推,执行到最后一步操作后,再在最后接上.catch()方法用于接收前面所有Promise中可能出现的错误。

  1. //模拟需要进行的操作
  2. let option = ["爬取音乐列表api", "爬取单曲id", "根据单曲id爬取具体资源"];
  3. //定义一个通用的请求数据的方法
  4. function getData(option) {
  5. return new Promise((resolve, reject) => {
  6. //利用setTimeout模拟真实网络中的请求速度
  7. setTimeout(() => {
  8. //真实情况Promise里返回的是通过异步请求得到的网络数据,这里暂且用文字提示
  9. resolve("success: " + option);
  10. }, 1000);
  11. })
  12. }
  13. //写法1:
  14. getData(option[0])
  15. .then(data => {
  16. console.log(data);
  17. // Do something
  18. return getData(option[1]);
  19. })
  20. .then(data => {
  21. console.log(data);
  22. // Do something
  23. return getData(option[2]);
  24. })
  25. .then(data => {
  26. // Do something
  27. console.log(data);
  28. })
  29. .catch(e => {
  30. console.log(e);
  31. })

运行结果如图:
Promise.gif
不过除此之外,还有一种优雅的写法,也是现目前利用同步代码解决异步操作的终极版本:async-await

2. async-await写法

在这里就不多介绍它们的基本用法和含义了,直接上操作

  1. /* 定义一个async函数 */
  2. async function load(){
  3. try{
  4. let res1 = await getData(option[0]);
  5. // Do something
  6. console.log(res1);
  7. let res2 = await getData(option[1]);
  8. // Do something
  9. console.log(res2);
  10. let res3 = await getData(option[2]);
  11. // Do something
  12. console.log(res3);
  13. }catch(e){
  14. console.log("error:",e);
  15. }
  16. }
  17. load();
  18. /*---------------------------------------------------------------------------------*/
  19. /* 或者可以通过执行匿名函数方式 */
  20. (async function(){
  21. try{
  22. let res1 = await getData(option[0]);
  23. // Do something
  24. console.log(res1);
  25. let res2 = await getData(option[1]);
  26. // Do something
  27. console.log(res2);
  28. let res3 = await getData(option[2]);
  29. // Do something
  30. console.log(res3);
  31. }catch(e){
  32. console.log("error:",e);
  33. }
  34. })();