JavaScript异步处理的那些事儿

栏目: JavaScript · 发布时间: 7年前

内容简介:之前总结了关于 JavaScript 异步的下面是关于JS异步处理的各种方案:

原文

之前总结了关于 JavaScript 异步的 事件循环与消息队列 机制以及 ES6 带来的 微任务与宏任务 的知识。传送门

下面是关于JS异步处理的各种方案:

callback >> ES6 Primise >> async/await
复制代码

没有异步处理

先看一段代码:

// 假设有一个耗时的异步请求 ajax,在 2 秒后打印日志

function ajax () {
  // do something...
  setTimeout(() => {
    console.log('Hello, Zavier Tang!')
  }, 2000)
}
ajax()
// do something...
console.log('The end.')

// The end.
// Hello, Zavier Tang!
复制代码

这里模拟了一个简单的异步网络请求,并在 2 秒后打印 "Hello, Zavier Tang!",然后做一些处理("do something")后,打印结束 "The end."。

结果是先打印的 "The end."。

显然这并不是我们要的结果,"异步请求" ajax 中的 setTimeout 并没有阻塞代码的执行,而是直接执行了 console.log()

异步的解决方案

1. 传统(可怕)的 callback 回调地狱

同样是上面的异步网络请求,这里使用 callback 回调函数的方式解决 JavaScript 同步带来的问题。

function ajax (fn) {
  // do something...
  setTimeout(() => {
    console.log('Hello, Zavier Tang!')
    fn()
  }, 2000)
}
ajax(() => {
  // do something...
  console.log('The end.')
})

// Hello, Zavier Tang!
// The end.
复制代码

这里我们直接把异步请求之后要做的一些操作做为回调函数,传递到 ajax 中去,并在异步请求结束后执行回调函数里的操作。

问题似乎已经解决了??但是,如果有多个异步请求,并且在每个异步请求完成后都执行一些操作,那代码就会像下面这样:

function ajax (fn) {
  // do something...
  setTimeout(() => {
    console.log('Hello, Zavier Tang!')
    fn()
  }, 500)
}

ajax(() => {
  // do something...
  console.log('The end 1.')
  ajax(() => {
    // do something...
    console.log('The end 2.')
    ajax(() => {
      // do something...
      console.log('The end 3.')
      ajax(() => {
        // do something...
        console.log('The end 4.')
        ajax(() => {
          // do something...
          console.log('The end 5.')
          // ......
          // ......
        })
      })
    })
  })
})

// Hello, Zavier Tang!
// The end 1.
// Hello, Zavier Tang!
// The end 2.
// Hello, Zavier Tang!
// The end 3.
// Hello, Zavier Tang!
// The end 4.
// Hello, Zavier Tang!
// The end 5.
复制代码

看起来很吓人!!

如果是这样:请求1结束后进行请求2,然后还有请求3、请求4、请求5,并且请求2还可能依赖于请求1的数据,请求3依赖于请求2的数据,不停的一层一层嵌套,对于错误的处理也极不方便,所以称之为 callback 回调地狱。

2. 下一代异步解决方案:Promise

ES6 的 Promise 被称为 JS 异步的下一代解决方案。

关于 Promise:

  • 用于异步计算。
  • 可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果。
  • 可以在对象之间传递和操作 Promise,方便处理队列。

接下来使用 Promise 处理异步:

function ajax (word) {
  return new Promise((resolve) => {
    // do something...
    setTimeout(() => {
      resolve('Hello ' + word)
    }, 500)
  })
}

ajax('请求1')
  .then((word) => {
    console.log(word)
    console.log('The end 1.')
    return ajax('请求2')
  })
  .then((word) => {
    console.log(word)
    console.log('The end 2.')
    return ajax('请求3')
  })
  .then((word) => {
    console.log(word)
    console.log('The end 3.')
  })
  // .catch(() => {})

// Hello 请求1
// The end 1.
// Hello 请求2
// The end 2.
// Hello 请求3
// The end 3.
复制代码

上面还是连续的异步请求,每次请求后打印日志。这样看起来比上面的回调地狱舒服多了,每个请求通过链式的调用,在最后可以对所有的请求进行错误处理。

但,似乎还并不是特别优雅。

3. 终极解决方案:async/await

关于 async/await 的简介:

  • async/await 是写异步代码的新方式,不同于以前的 callback 回调函数和 Promise。
  • async/await 是基于 Promise 实现的,不能用于普通的回调函数。
  • async/await 与 Promise 一样,是非阻塞的。
  • async/await 使得异步代码看起来像同步代码。

体验一下神奇的 async/await:

// 接上面的代码
async function doAsync () {
  const word1 = await ajax('请求1')
  console.log(word1)
  console.log('The end 1')

  const word2 = await ajax('请求2')
  console.log(word2)
  console.log('The end 2')

  const word3 = await ajax('请求3')
  console.log(word3)
  console.log('The end 3')
}
doAsync()

// Hello 请求1
// The end 1
// Hello 请求2
// The end 2
// Hello 请求3
// The end 3
复制代码

这样看起来,更优雅了。没有任何括号,也没有 callback,没有 then,直接申明 async,使用 await 等待异步执行完成,看起来也更像是同步的代码。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Numerical Recipes 3rd Edition

Numerical Recipes 3rd Edition

William H. Press、Saul A. Teukolsky、William T. Vetterling、Brian P. Flannery / Cambridge University Press / 2007-9-6 / GBP 64.99

Do you want easy access to the latest methods in scientific computing? This greatly expanded third edition of Numerical Recipes has it, with wider coverage than ever before, many new, expanded and upd......一起来看看 《Numerical Recipes 3rd Edition》 这本书的介绍吧!

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具