简述
在平时coding中,有时可能会遇到某些业务场景需要在同一时间只能做一件事,做完了才能做下一件事情。这种很明显符合同步操作的逻辑,但如果不采取某些优雅的编程方式可能就会导致如图这样的结果,很有可能就会产生传说中的回调地狱。
需求
假设现在有这样一个场景,我们需要去爬取一个网站上的数据,需要先将大致内容爬取下来,再逐步去筛选小部分的内容,再根据小部分的内容去获取具体的资源。如何利用**Promise**去实现这个需求呢?
1. Promise写法
//模拟需要进行的操作let option = ["爬取音乐列表api", "爬取单曲id", "根据单曲id爬取具体资源"];//定义一个通用的请求数据的方法function getData(option) {return new Promise((resolve, reject) => {//利用setTimeout模拟真实网络中的请求速度setTimeout(() => {//真实情况Promise里返回的是通过异步请求得到的网络数据,这里暂且用文字提示resolve("success: " + option);}, 1000);})}
现在就需要我们进行一步又一步地操作了…
执行getData()函数,由于这个函数返回的是Promise对象,所以可以利用.then()方法来接收,在.then()方法中对返回的数据进行处理以后,又在.then()方法中执行getData()函数,getData()函数中传入下一步要操作的内容。以此类推,执行到最后一步操作后,再在最后接上.catch()方法用于接收前面所有Promise中可能出现的错误。
//模拟需要进行的操作let option = ["爬取音乐列表api", "爬取单曲id", "根据单曲id爬取具体资源"];//定义一个通用的请求数据的方法function getData(option) {return new Promise((resolve, reject) => {//利用setTimeout模拟真实网络中的请求速度setTimeout(() => {//真实情况Promise里返回的是通过异步请求得到的网络数据,这里暂且用文字提示resolve("success: " + option);}, 1000);})}//写法1:getData(option[0]).then(data => {console.log(data);// Do somethingreturn getData(option[1]);}).then(data => {console.log(data);// Do somethingreturn getData(option[2]);}).then(data => {// Do somethingconsole.log(data);}).catch(e => {console.log(e);})
运行结果如图:
不过除此之外,还有一种优雅的写法,也是现目前利用同步代码解决异步操作的终极版本:async-await
2. async-await写法
在这里就不多介绍它们的基本用法和含义了,直接上操作
/* 定义一个async函数 */async function load(){try{let res1 = await getData(option[0]);// Do somethingconsole.log(res1);let res2 = await getData(option[1]);// Do somethingconsole.log(res2);let res3 = await getData(option[2]);// Do somethingconsole.log(res3);}catch(e){console.log("error:",e);}}load();/*---------------------------------------------------------------------------------*//* 或者可以通过执行匿名函数方式 */(async function(){try{let res1 = await getData(option[0]);// Do somethingconsole.log(res1);let res2 = await getData(option[1]);// Do somethingconsole.log(res2);let res3 = await getData(option[2]);// Do somethingconsole.log(res3);}catch(e){console.log("error:",e);}})();
