澳门威斯尼人平台登录Async/Await替代Promise的6个理由

Async/Await替代Promise的6个理由

2017/04/02 · JavaScript · async, await

原来的书文出处: Mostafa Gaafar   译文出处:Fundebug   

译者按: Node.js的异步编制程序形式可行巩固了应用品质;不过回调鬼世界却让人心有余悸,Promise让我们拜别回调函数,写出更优雅的异步代码;在实施进程中,却发现Promise并不康健;技能进步是前行的,此时,我们有了Async/Await。

Node.js 7.6早就支撑async/await了,借令你还不曾试过,那篇博客将报告您干吗要用它。

3. 准绳语句

上面示例中,须要获取数据,然后依照重回数据调控是直接重回,照旧三翻五次得到越多的数据。

const makeRequest = () => {
  return getJSON()
    .then(data => {
      if (data.needsAnotherRequest) {
        return makeAnotherRequest(data)
          .then(moreData => {
            console.log(moreData)
            return moreData
          })
      } else {
        console.log(data)
        return data
      }
    })
}

地点的代码嵌套(6层卡塔尔国、括号、return语句十分轻易令人看不懂。

使用Async/Await编写:

const makeRequest = async () => {
  const data = await getJSON()
  if (data.needsAnotherRequest) {
    const moreData = await makeAnotherRequest(data);
    console.log(moreData)
    return moreData
  } else {
    console.log(data)
    return data    
  }
}

4. 中间值

你很或然蒙受过那样的景况,调用promise1,使用promise1重临的结果去调用promise2,然后选取两个的结果去调用promise3。你的代码很大概是如此的:

JavaScript

const makeRequest = () => { return promise1() .then(value1 => { return promise2(value1) .then(value2 => { return promise3(value1, value2) }) }) }

1
2
3
4
5
6
7
8
9
const makeRequest = () => {
  return promise1()
    .then(value1 => {
      return promise2(value1)
        .then(value2 => {        
          return promise3(value1, value2)
        })
    })
}

设若promise3无需value1,能够很简短地将promise嵌套铺平。假使您忍受不住嵌套,你能够将value 1 & 2 放进Promise.all来防止深层嵌套:

JavaScript

const makeRequest = () => { return promise1() .then(value1 => { return Promise.all([value1, promise2(value1)]) }) .then(([value1, value2]) => { return promise3(value1, value2) }) }

1
2
3
4
5
6
7
8
9
const makeRequest = () => {
  return promise1()
    .then(value1 => {
      return Promise.all([value1, promise2(value1)])
    })
    .then(([value1, value2]) => {      
      return promise3(value1, value2)
    })
}

这种办法为了可读性捐躯了语义。除了制止嵌套,并从未其他理由将value1和value2放在一个数组中。

行使async/await的话,代码会变得特别轻松和直观。

JavaScript

const makeRequest = async () => { const value1 = await promise1() const value2 = await promise2(value1) return promise3(value1, value2) }

1
2
3
4
5
const makeRequest = async () => {
  const value1 = await promise1()
  const value2 = await promise2(value1)
  return promise3(value1, value2)
}

5. 错误栈

const makeRequest = () => {
  return callAPromise()
    .then(() => callAPromise())
    .then(() => callAPromise())
    .then(() => callAPromise())
    .then(() => callAPromise())
    .then(() => {
      throw new Error("oops");
    })
}
makeRequest()
  .catch(err => {
    console.log(err);
    // output
    // Error: oops at callAPromise.then.then.then.then.then (index.js:8:13)
  })

上述示范中调用了四个promise,若是promise链中有个别地点抛出了叁个要命,再次回到的荒诞栈未有交到错误产生的职位音信。

async/await中的错误栈会指向错误所在的函数:

const makeRequest = async () => {
  await callAPromise()
  await callAPromise()
  await callAPromise()
  await callAPromise()
  await callAPromise()
  throw new Error("oops");
}
makeRequest()
  .catch(err => {
    console.log(err);
    // output
    // Error: oops at makeRequest (index.js:7:9)
  })

在开荒进程中,恐怕那或多或少优势并非极大。不过,如若是剖判坐褥条件的一无是处日志时,它将不胜实用。

5. 错误栈

上面示例中调用了多少个Promise,倘若Promise链中有些地方抛出了三个错误:

JavaScript

const makeRequest = () => { return callAPromise() .then(() => callAPromise()) .then(() => callAPromise()) .then(() => callAPromise()) .then(() => callAPromise()) .then(() => { throw new Error("oops"); }) } makeRequest() .catch(err => { console.log(err); // output // Error: oops at callAPromise.then.then.then.then.then (index.js:8:13) })

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const makeRequest = () => {
  return callAPromise()
    .then(() => callAPromise())
    .then(() => callAPromise())
    .then(() => callAPromise())
    .then(() => callAPromise())
    .then(() => {
      throw new Error("oops");
    })
}
makeRequest()
  .catch(err => {
    console.log(err);
    // output
    // Error: oops at callAPromise.then.then.then.then.then (index.js:8:13)
  })

Promise链中回到的不当栈未有交到错误产生地方的头脑。更不佳的是,它会误导大家;错误栈中必定要经过之处的函数名字为callAPromise,但是它和谬误未有涉及。(文件名和行号依旧管用的卡塔尔国。

可是,async/await中的错误栈会指向错误所在的函数:

JavaScript

const makeRequest = async () => { await callAPromise() await callAPromise() await callAPromise() await callAPromise() await callAPromise() throw new Error("oops"); } makeRequest() .catch(err => { console.log(err); // output // Error: oops at makeRequest (index.js:7:9) })

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const makeRequest = async () => {
  await callAPromise()
  await callAPromise()
  await callAPromise()
  await callAPromise()
  await callAPromise()
  throw new Error("oops");
}
makeRequest()
  .catch(err => {
    console.log(err);
    // output
    // Error: oops at makeRequest (index.js:7:9)
  })

在开辟条件中,那或多或少优势并十分的小。不过,当你分析生产条件的不当日志时,它将不胜实用。当时,知道不当爆发在makeRequest比知道不当发生在then链中要好。

为什么Async/Await更好?

6. 调试

最后一点,也是不行重要的少数在于,async/await能够使得代码调试更简便。2个理由使得调节和测量试验Promise变得老大忧伤:

  • 不能够在回来证明式的箭头函数中设置断点

澳门威斯尼人平台登录 1

  • 借使您在.then代码块中设置断点,使用Step Over火速键,调节和测量试验器不会跳到下一个.then,因为它只会跳过异步代码。

利用await/async时,你不再要求那么多箭头函数,那样你就能够像调节和测验同步代码同样跳过await语句。

澳门威斯尼人平台登录 2

2. 错误处理

Async/Await让try/catch能够同临时间管理一同和异步错误。在上边包车型客车promise示例中,try/catch不可能管理JSON.parse的大谬不然,因为它在Promise中。大家要求使用.catch,那样错误管理代码非常冗余。何况,在大家的莫过于临蓐代码会更加的头昏眼花。

const makeRequest = () => {
  try {
    getJSON()
      .then(result => {
        // JSON.parse可能会出错
        const data = JSON.parse(result)
        console.log(data)
      })
      // 取消注释,处理异步代码的错误
      // .catch((err) => {
      //   console.log(err)
      // })
  } catch (err) {
    console.log(err)
  }
}

使用aync/await的话,catch能处理JSON.parse错误:

const makeRequest = async () => {
  try {
    // this parse may fail
    const data = JSON.parse(await getJSON())
    console.log(data)
  } catch (err) {
    console.log(err)
  }
}

2. 错误管理

Async/Await让try/catch能够何况处理一齐和异步错误。在底下的promise示例中,try/catch不能管理JSON.parse的荒谬,因为它在Promise中。大家须求使用.catch,这样错误管理代码特别冗余。何况,在大家的骨子里生育代码会愈发目迷五色。

JavaScript

const makeRequest = (卡塔尔 => { try { getJSON(卡塔尔(英语:State of Qatar) .then(result => { // JSON.parse恐怕会出错 const data = JSON.parse(result卡塔尔(قطر‎ console.log(data卡塔尔(英语:State of Qatar)}卡塔尔国 // 撤消注释,管理异步代码的失实 // .catch((err卡塔尔(英语:State of Qatar) => { // console.log(err卡塔尔(قطر‎ // }卡塔尔(英语:State of Qatar) } catch (err卡塔尔(英语:State of Qatar) { console.log(err卡塔尔 } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const makeRequest = () => {
  try {
    getJSON()
      .then(result => {
        // JSON.parse可能会出错
        const data = JSON.parse(result)
        console.log(data)
      })
      // 取消注释,处理异步代码的错误
      // .catch((err) => {
      //   console.log(err)
      // })
  } catch (err) {
    console.log(err)
  }
}

使用aync/await的话,catch能处理JSON.parse错误:

JavaScript

const makeRequest = async () => { try { // this parse may fail const data = JSON.parse(await getJSON()) console.log(data) } catch (err) { console.log(err) } }

1
2
3
4
5
6
7
8
9
const makeRequest = async () => {
  try {
    // this parse may fail
    const data = JSON.parse(await getJSON())
    console.log(data)
  } catch (err) {
    console.log(err)
  }
}

Async/Await语法

Promise写法:

const makeRequest = () =>
  getJSON()
    .then(data => {
      console.log(data)
      return "done"
    })
makeRequest()

Async/Await写法:

const makeRequest = async () => {
  console.log(await getJSON())
  return "done"
}
makeRequest()

亲自过问中,getJSON函数重临二个promise,那一个promise成功resolve时会再次回到四个promise对象。我们只是调用这一个函数,打字与印刷重临的JSON对象,然后回来“done”。

它们有风姿罗曼蒂克部分细微差异:

  • 函数前边多了一个async关键字。await关键字只可以用在async定义的函数内。async函数会隐式的归来二个promise,该promise的resolve值便是函数return的值。(示例中resolve值就是字符串"done"卡塔尔(قطر‎
  • 第1点暗中表示大家不可能在最外层代码中利用await,因为不在async函数内。
//不能在最外层代码中使用await
await makeRequest()

//这是会出事的
makeRequest().then((result) => {
  //代码
})

await getJSON(卡塔尔(英语:State of Qatar)表示console.log会等到getJSON的promise成功reosolve之后再实行。

忧虑

对于Async/Await,大概你有部分合理的狐疑:

  • 它使得异步代码不在明显: 大家曾经习贯了用回调函数恐怕.then来辨别异步代码,大家也许供给花数个礼拜去习贯新的标识。可是,C#富有那个性情已经比超多年了,领会它的意中人应该清楚暂且的有一点不平价是值得的。
  • Node 7不是LTS(长时间支撑版本): 不过,Node 8下一个月就能发表,将代码迁移到新版本会特简单。

 

1 赞 1 收藏 评论

澳门威斯尼人平台登录 3

6. 调试

async/await能够使代码更方便人民群众意考察试。
promise调节和测验非常疼苦:

  • 无法在回去表明式的箭头函数中安装断点
const makeRequest = () => {
    return callAPromise()
      .then(() => callAPromise())
      .then(() => callAPromise())
      .then(() => callAPromise())
      .then(() => callAPromise())
}
  • 少年老成经在.then代码块中装置断点,使用Step Over快捷键,调节和测验器不会调到下几个.then,因为它只会跳过异步代码。

运用async/await时,不再必要那么多箭头函数,那样就足以像调节和测量试验同步代码相符跳过await语句。

const makeRequest = async () => {
    await callAPromise()
    await callAPromise()
    await callAPromise()
    await callAPromise()
}

Async/Await简介

对于尚未据他们说过async/await的相恋的人,上边是简要介绍:

  • async/await是写异步代码的新措施,在此以前的点子有回调函数Promise
  • async/await是依附Promise完毕的,它无法用于平常的回调函数。
  • async/await与Promise相仿,是非拥塞的。
  • async/await使得异步代码看起来像一块代码,那多亏它的魔力处处。

Async/Await简介

  • async/await是写异步代码的新方式,在此在此以前的措施有回调函数和Promise。
  • async/await是依赖Promise达成的,它不可能用于日常的回调函数。
  • async/await与Promise相通,是非拥塞的。
  • async/await使得异步代码看起来像一块代码,那就是它的吸引力处处。

结论

Async/Await是这两天JavaScript增加的最革命性的的性状之大器晚成。它会令你开采Promise的语法有多不佳,并且提供了二个直观的代表格局。

4. 中间值

你也许碰着过这么的现象,调用promise1,使用promise1重回的结果调用promise2,然后使用两者的结果调用promise3。使用promise的代码是:

const makeRequest = () => {
  return promise1()
    .then(value1 => {
      return promise2(value1)
        .then(value2 => {        
          return promise3(value1, value2)
        })
    })
}

怎么promise3不采纳value1,能够相当粗略的将promise铺平。假设忍受不住嵌套,能够将value1 & value2放进Promise.all来防止深层嵌套:

const makeRequest = () => {
  return promise1()
    .then(value1 => {
      return Promise.all([value1, promise2(value1)])
    })
    .then(([value1, value2]) => {      
      return promise3(value1, value2)
    })
}

这种方式为了可读性捐躯了语义,除了幸免嵌套,并未其余理由将value1和value2放在二个数组中。

接纳async/await的话,代码会变得相当轻巧和直观:

const makeRequest = async () => {
  const value1 = await promise1()
  const value2 = await promise2(value1)
  return promise3(value1, value2)
}

3. 尺度语句

上边示例中,须要获取数据,然后依据重回数据调整是平素回到,依旧持续获得越多的多少。

JavaScript

const makeRequest = () => { return getJSON() .then(data => { if (data.needsAnotherRequest) { return makeAnotherRequest(data) .then(moreData => { console.log(moreData) return moreData }) } else { console.log(data) return data } }) }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const makeRequest = () => {
  return getJSON()
    .then(data => {
      if (data.needsAnotherRequest) {
        return makeAnotherRequest(data)
          .then(moreData => {
            console.log(moreData)
            return moreData
          })
      } else {
        console.log(data)
        return data
      }
    })
}

这一个代码望着就高烧。嵌套(6层),括号,return语句超轻巧令人以为迷闷,而它们只是必要将最终结果传递到最外层的Promise。

位置的代码应用async/await编写能够大大地进步可读性:

JavaScript

const makeRequest = async () => { const data = await getJSON() if (data.needsAnotherRequest) { const moreData = await makeAnotherRequest(data); console.log(moreData) return moreData } else { console.log(data) return data } }

1
2
3
4
5
6
7
8
9
10
11
const makeRequest = async () => {
  const data = await getJSON()
  if (data.needsAnotherRequest) {
    const moreData = await makeAnotherRequest(data);
    console.log(moreData)
    return moreData
  } else {
    console.log(data)
    return data    
  }
}

1. 简洁

由示例可见,使用Async/Await显著节约了成都百货上千代码。大家无需写.then,无需写佚名函数管理Promise的resolve值,也没有须求定义多余的data变量,还防止了嵌套代码。那些小的长处会急速累加起来,那在以往的代码示例中会越发分明。

Async/Await语法

以身作则中,getJSON函数再次回到一个promise,那一个promise成功resolve时会重回一个json对象。大家只是调用这么些函数,打印重回的JSON对象,然后回来”done”。

选拔Promise是那般的:

JavaScript

const makeRequest = () => getJSON() .then(data => { console.log(data) return "done" }) makeRequest()

1
2
3
4
5
6
7
const makeRequest = () =>
  getJSON()
    .then(data => {
      console.log(data)
      return "done"
    })
makeRequest()

行使Async/Await是这么的:

JavaScript

const makeRequest = async () => { console.log(await getJSON()) return "done" } makeRequest()

1
2
3
4
5
const makeRequest = async () => {
  console.log(await getJSON())
  return "done"
}
makeRequest()

它们有风流洒脱部分细微不相同:

  • 函数前面多了二个aync关键字。await关键字只好用在aync定义的函数内。async函数会隐式地赶回叁个promise,该promise的reosolve值正是函数return的值。(示例中reosolve值正是字符串”done”卡塔尔(قطر‎
  • 第1点暗中表示大家不能够在最外层代码中利用await,因为不在async函数内。

JavaScript

// 不能够在最外层代码中选取await await makeRequest(卡塔尔 // 这是会出事情的 makeRequest(卡塔尔(قطر‎.then((result卡塔尔(英语:State of Qatar) => { // 代码 }卡塔尔(英语:State of Qatar)

1
2
3
4
5
6
// 不能在最外层代码中使用await
await makeRequest()
// 这是会出事情的
makeRequest().then((result) => {
  // 代码
})

await getJSON(卡塔尔表示console.log会等到getJSON的promise成功reosolve之后再进行。

1. 简洁

由示例可以知道,使用Async/Await明显节约了重重代码。我们不要求写.then,无需写无名氏函数管理Promise的resolve值,也无需定义多余的data变量,还幸免了嵌套代码。那个小的长处会迅速累积起来,那在今后的代码示例中会越发鲜明。

为什么Async/Await更好?

本文由澳门威斯尼人平台登录发布于Web前端,转载请注明出处:澳门威斯尼人平台登录Async/Await替代Promise的6个理由

相关阅读