原贴链接:javascript异步之async(二)
这是javascript异步系列文章的第八篇

昨天讨论了javascript的Generator生成器

简单回顾

Generator生成器,区别于普通函数,它可以执行暂停操作,

而next就是驱动Generator的暂停和启动的“开关”

yield只能写在Generator内部,通过next启动生成器后,遇到yield就会暂停

yield和next之间可以相互传值

第一个next不需要传值,第一个next只是用来启动Generator

但是它可以接受第一个yield后面的值(前提是如果有值存在,否则就是undefined)

昨天的栗子🌰有点“hello world”,今天增加一点复杂度

一个需求

需求如下:

现在有接口1,接口2,接口3 按顺序输出接口1,接口2,接口3的请求值

我们还是使用Jquery处理ajax请求

  1. <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>

还是easy-mock上面的那三个接口,为了拉长接口三的执行时间,我这接口了加入了长度为10-20 的数组 保证它比接口一和接口二慢

因为后面要对这三个接口的请求进行封装,先把代码列出来,方便查询参考

  1. function loadData1() {
  2. $.ajax({
  3. url: "https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/promise1",
  4. success: ({
  5. data,
  6. success
  7. }) => {
  8. if (success) {
  9. console.log(data);
  10. }
  11. }
  12. });
  13. }
  14. function loadData2() {
  15. $.ajax({
  16. url: "https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/promise2",
  17. success: ({
  18. data
  19. }) => {
  20. console.log(data);
  21. }
  22. });
  23. }
  24. function loadData3() {
  25. $.ajax({
  26. url: "https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/mock",
  27. success: ({
  28. data,
  29. success
  30. }) => {
  31. if (success) {
  32. console.log(data);
  33. }
  34. }
  35. });
  36. }

回调函数

常规做法

即,loadData1执行成功后,执行loadData2,loadData2执行成功后执行loadData3

  1. function getData() {
  2. $.ajax({
  3. url: "https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/promise1",
  4. success: ({
  5. data,
  6. success
  7. }) => {
  8. if (success) {
  9. console.log(data);
  10. $.ajax({
  11. url: "https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/promise2",
  12. success: ({
  13. data
  14. }) => {
  15. console.log(data);
  16. if (data.name) {
  17. $.ajax({
  18. url: "https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/mock",
  19. success: ({
  20. data,
  21. success
  22. }) => {
  23. if (success) {
  24. console.log(data);
  25. }
  26. }
  27. });
  28. }
  29. }
  30. });
  31. }
  32. }
  33. });
  34. }
  35. getData()

输出符合预期
image.png

回调地狱,说的就是你😂

Promise

来一个Promise实现的,顺便对前面的Promise进行复习

  1. /*
  2. *对ajax的请求做了一个简单的封装
  3. *@ajaxUrl,接口地址,公共部分已经抽取
  4. *@successCb,ajax请求成功后的回调函数
  5. */
  6. function ajaxFun(ajaxUrl, successCb) {
  7. $.ajax({
  8. url: `https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/${ajaxUrl}`,
  9. success: res => successCb(res)
  10. });
  11. }
  12. //promise
  13. new Promise((resolve, reject) => {
  14. ajaxFun("promise1", ({
  15. data,
  16. success
  17. }) => {
  18. if (success) {
  19. console.log('接口一', data);
  20. resolve(data)
  21. }
  22. })
  23. })
  24. .then(() => {
  25. ajaxFun("promise2", ({
  26. data
  27. }) => {
  28. if (data.name) {
  29. console.log('接口二', data);
  30. }
  31. })
  32. })
  33. .then(() => {
  34. ajaxFun("mock", ({
  35. data,
  36. success
  37. }) => {
  38. if (success) {
  39. console.log('接口三', data);
  40. }
  41. })
  42. })

Generator实现

  1. function loadData1() {
  2. ajaxFun("promise1", ({
  3. data,
  4. success
  5. }) => {
  6. if (success) {
  7. console.log('接口一', data);
  8. it.next()//“接口一成功返回后,执行下一步”
  9. }
  10. })
  11. }
  12. function loadData2() {
  13. ajaxFun("promise2", ({
  14. data
  15. }) => {
  16. if (data.name) {
  17. console.log('接口二', data);
  18. it.next()//“接口二成功返回后,执行下一步”
  19. }
  20. })
  21. }
  22. function loadData3() {
  23. ajaxFun("mock", ({
  24. data,
  25. success
  26. }) => {
  27. if (success) {
  28. console.log('接口三', data);
  29. }
  30. })
  31. }
  32. function* getData() {
  33. yield loadData1()
  34. yield loadData2()
  35. yield loadData3()
  36. }
  37. const it = getData()
  38. it.next()//“启动生成器”

先弄一个遍历器出来,然后通过it.next(),启动遍历器

执行第一个接口请求,当第一个接口请求成功了,继续next(),以此类推

我想很少有人会通过Generator实现多个异步同步执行,但是async可以

下次我们尝试用async await 来实现异步请求同步化

END