直接调用(异步调异步)

  1. function fn1() {
  2. setTimeout(() => {
  3. console.log('fn1执行')
  4. fn2('fn1传递过去的参数')
  5. }, 1000)
  6. }
  7. function fn2(data) {
  8. setTimeout(() => {
  9. console.log('fn2执行', data)
  10. fn3('fn2传递过去的参数')
  11. }, 1000)
  12. }
  13. function fn3(data) {
  14. setTimeout(() => {
  15. console.log('fn3执行', data)
  16. }, 1000)
  17. }
  18. fn1()

执行结果如下:
Javascript中如何让多个异步按顺序执行 - 图1

我们发现这种方式虽然能实现,但是代码量一旦变多,可读性就降低了。

Promise的方式

  1. function fn1() {
  2. return new Promise((resolve, reject) => {
  3. console.log('fn1执行')
  4. setTimeout(() => {
  5. console.log('fn1结束')
  6. resolve('fn1传递过去的参数')
  7. }, 1000)
  8. })
  9. }
  10. function fn2(data) {
  11. return new Promise((resolve, reject) => {
  12. console.log('fn2执行,接收的参数', data)
  13. setTimeout(() => {
  14. resolve('fn2传递过去的参数')
  15. }, 1000)
  16. })
  17. }
  18. function fn3(data) {
  19. return new Promise((resolve, reject) => {
  20. console.log('fn3执行,接收的参数', data)
  21. setTimeout(() => {
  22. resolve('fn3传递过去的参数')
  23. }, 1000)
  24. })
  25. }
  26. fn1().then(fn2).then(fn3).then(res => {
  27. console.log('最后一个', res)
  28. })

执行结果如下:
Javascript中如何让多个异步按顺序执行 - 图2

生成器的方式

生成器就是能返回一个迭代器的函数,它也是一个函数,对比普通的函数,多了一个*,在它的函数体内可以使用yield关键字,函数会在每个yield后暂停,等待,直到这个生成的对象,调用下一个next(),每调用一次next会往下执行一次yieId,然后暂停。

  1. function* main() {
  2. const res1 = yield fn1('开始')
  3. const res2 = yield fn2(res1)
  4. const res3 = yield fn3(res2)
  5. console.log(res3, '全部执行完毕')
  6. }
  7. const task = main()
  8. task.next()
  9. function fn1(data) {
  10. setTimeout(() => {
  11. console.log('fn1执行', data)
  12. task.next('fn1执行完毕')
  13. }, 1000)
  14. }
  15. function fn2(data) {
  16. setTimeout(() => {
  17. console.log('fn2执行', data)
  18. task.next('fn2执行完毕')
  19. }, 1000)
  20. }
  21. function fn3(data) {
  22. setTimeout(() => {
  23. console.log('fn3执行', data)
  24. task.next('fn3执行完毕')
  25. }, 1000)
  26. }
  27. console.log('我是最开始同步执行的')

执行结果如下:
Javascript中如何让多个异步按顺序执行 - 图3