实战学习JavaScript Async/Await – codeburst

实战学习JavaScript ES 2017: Async/Await

用一个简单的例子解释Async/Await

前置知识

在ES 2017中引入了 异步 函数( Asynchronous functions),简单来说在javascript中异步函数是一种更简约的处理异步代码的方式。为了准确地理解他们的本质以及运作方式,首先我们需要理解 Promises

如果你不知道什么是Promises,你应该首先 阅读这篇关于promises的文章 只有完全理解了 Promises后才能理解Async/Await

什么是Async/Await?

  • JavaScript中最新的书写异步代码的方式

  • 非阻塞式(就像promises和callback一样)

  • Async/Await的目的是为了简化promises的链式代码的书写

  • 异步函数返回一个Promise,如果函数抛出一个错误,表明Promise被拒绝/执行失败,如果函数返回了值,表明Promise被接受/执行成功。

语法

写异步函数非常简单,你只需要在 function 前面添加关键字 async 即可:

**// Normal Function**

function add(x,y){
  return x + y;
}
**// Async Function**

async function add(x,y){
  return x + y;
}

Await关键字

异步函数使用 await 关键字,用于暂停 async 函数并等待Promise解析来进行下一步。

举栗子时间

话不多说,让我来看一个例子!首先我们使用promises来写代码,一旦运行成功,我们用async/await重写我们的函数,来看看它是如何的简单!

如果你是用Google Chrome浏览器来实验代码的话,请确保将代码输入开发终端中,你可以通过Ctrl+Shift+J (Windows / Linux) 或者 Cmd+Opt+J (Mac)来开启开发终端。

代码如下:

function doubleAfter2Seconds(x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x * 2);
    }, 2000);
  });
}

在这段代码中我们创建了一个函数 doubleAfter2Seconds ,这个函数接受一个数值作为输入参数,然后过2秒之后将这个数值翻倍。

我们可以输入数字 10 来执行这个函数,等Promise执行成功,我们将返回值记录下来并输出到终端,执行代码如下:

doubleAfter2Seconds(10).then((r) => {
  console.log(r);
});

棒极了!

但是,如果我们想通过我们的函数运行几个不同的值并添加结果呢?不幸的是我们不能单纯地调用这些函数并他们加起来进行输出。

let sum =   doubleAfter2Seconds(10)
          + doubleAfter2Seconds(20)
          + doubleAfter2Seconds(30);
console.log(sum);

// undefined

上面的代码存在的问题是它实际上没等待Promises解析成功就在终端进行了输出。

一种解决方法是链式调用promise。为了达到这一目的我们创建一个新函数 addPromise 。这个函数接受一个输入值,并返回一个Promise对象。示例代码如下:

function addPromise(x){
  return new Promise(resolve => {
    // Code goes here...   
    // resolve()
  });
}

棒极了!现在我们将这个函数添加到之前的函数 doubleAfter2Seconds 中去,一旦完成后我们就可以得到叠加值。在这个例子中,我们返回 x + 2*a + 2*b + 2*c ,代码如下:

function addPromise(x){
  return new Promise(resolve => {
    doubleAfter2Seconds(10).then((a) => {
      doubleAfter2Seconds(20).then((b) => {
        doubleAfter2Seconds(30).then((c) => {
          resolve(x + a + b + c);
        })
      })
    })
  });
}

让我们一行一行地回顾代码

  • 首先,我们创建了函数 addPromise ,这个函数接受一个输入值。

  • 接着,我们返回了新Promise对象,为了简化代码,我们并没有处理失败/错误。

  • 再下来,我们调用 doubleAfter2Seconds 函数,传入值 10 ,2秒之后,结果 20 储存在变量 a 中返回。

  • 我们对 doubleAfter2Seconds 函数再次进行调用,这次我们传入值 20 ,2秒之后,将结果 40 储存在变量 b 中返回。

  • 我们最后一次调用 doubleAfter2Seconds ,这次传入传值 30 ,2秒之后,将结果 60 储存在变量 c 中返回。

  • 最后,我们解析Promise成功,并返回值 10 + 20 + 40 + 60 或者 130

我们把所有的代码整合起来就是这样:

function doubleAfter2Seconds(x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x * 2);
    }, 2000);
  });
}

function addPromise(x){
  return new Promise(resolve => {
    doubleAfter2Seconds(10).then((a) => {
      doubleAfter2Seconds(20).then((b) => {
        doubleAfter2Seconds(30).then((c) => {
          resolve(x + a + b + c);
        })
      })
    })
  });
}

从 Promises 走向 Async/Await.

棒极了!现在我们来看看使用Async/Await来实现上面的代码是多简单。

去掉函数 addPromise ,穿件一个新函数 addAsync ,这个新函数实现的功能与 addPromise 一样,在写新函数是我们使用关键字 async ,代码如下:

async function addAsync(x) {
  // code here...
}

这样我们就创建了一个异步函数,我们可以使用关键字 await 来等待Promise进行解析,如此的简单:

async function addAsync(x) {
  const a = await doubleAfter2Seconds(10);
  const b = await doubleAfter2Seconds(20);
  const c = await doubleAfter2Seconds(30);
  return x + a + b + c;
}

而这就是全部的代码。

如您所见,我们依旧保留了 doubleAfter2Seconds 函数,只是调用 addAsync() 函数并传入值 10 ,然后输出返回值。让我们一步一步解释这段代码:

  • 首先我们调用 addAsync(10) ,并传入值 10

  • 然后我们获取 a 的值,因为我们使用了关键字 await ,我们的函数自动暂停2秒钟以解析promise,一旦解析成功, a = 20

const a = await` doubleAfter2Seconds`(10);`
  • 接着我们获取 b 的值,因为我们使用了关键字 await ,我们的函数自动暂停2秒钟以等待promise解析,一旦解析成功, b = 40
const b = await` doubleAfter2Seconds`(20);`
    • 接着我们获取 c 的值,因为我们使用了关键字 await ,我们的函数自动暂停2秒钟以等待promise解析,一旦解析成功, c = 60
const c = await` doubleAfter2Seconds`(30);`
  • 最后,我们返回 x + a + b + c ,因为我们传入了 10 作为输入值,我们将返回 10 + 20 + 40 + 60

  • 整整6秒种后,代码 console.log(sum) 被执行,传入参数 10 + 20 + 40 + 60 ,结果就在终端中输出 130

这是这样!你已经学会在Javascript中创建异步函数了!

如你所见,异步函数返回Promise对象,所以可以很方便地处理Promises对象,使用异步函数取代长长的链式promise也让我们的代码也变得更加清晰易读。

众成翻译稿源:众成翻译 (源链) | 关于 | 阅读提示

本站遵循[CC BY-NC-SA 4.0]。如您有版权、意见投诉等问题,请通过eMail联系我们处理。
酷辣虫 » 前端开发 » 实战学习JavaScript Async/Await – codeburst

喜欢 (0)or分享给?

专业 x 专注 x 聚合 x 分享 CC BY-NC-SA 4.0

使用声明 | 英豪名录