运用ES2017 async/await函数的注重点

跟着node 7.6.0正式实装async/await函数,js的异步编程变的比以往越发轻易。然则,在我们周全投入async/await的度量之前,有必要对这个特征做一些仔细的相识。

誊写情势

基本上,任何一个函数都能够成为async函数,以下都是正当的誊写情势:

  • 函数声明
    async function foo () {}

  • 函数表达式
    const foo = async function () {}

  • 要领定义
    const obj = { async foo () {} }

  • 箭头函数
    async () => {}

async函数老是返回Promise

纵然返回值只是一个primitive值,async函数也会经由过程return自动将返回值包装成一个Promise对象返回。
因而,下面两组函数是等价的。

一般 (Fulfill)

// async函数
async function foo () {
  return 'a'
}

// Promise
function foo () {
  return Promise.resolve('a')
}

非常 (Reject)

// async函数
async function foo () {
  throw new Error('error')
}

// Promise
function foo () {
  return Promise.reject(new Error('error'))
}

注重:当返回值自身就是一个Promise对象时,async函数的return并不会对返回值举行二次包装。

await老是按递次实行

运用async函数之前,我们还得搞清楚它的运行机制。尤其是在实行递次上,完整用同步的头脑或许并不适用于async函数。

斟酌下面的代码

function asyncGet (x) {
  return new Promise(resolve => setTimeout(() => {
    console.log('a')
    resolve(x)
  }, 500))
}

async function test () {
  console.log('b')
  const x = 3 + 5
  console.log(x)

  const a = await asyncGet(1)
  console.log(a)

  const b = await asyncGet(2)
  console.log(b)

  console.log('c')  
  return a + b
}

const now = Date.now()
console.log('d')
test().then(x => {
  console.log(x)
  console.log(`elapsed: ${Date.now() - now}`)
})
console.log('f')
  1. async函数和一般函数一样按递次实行,同时,在实行到await语句时,返回一个Promise对象

  2. await能够明白为将async函数挂起,直到守候的Promise被fulfill或许reject,再继承实行以后的代码

  3. async函数的返回值和一般Promise没有区分

因而,上面代码输出应该是

d
b
8
f
a
1
a
2
c
3
elapsed: 1010

注重 d 和 f 中心的输出

让我们再来看一个夹杂了Promise的版本。

function asyncGet (x) {
  return new Promise(resolve => setTimeout(() => {
    console.log('a')
    resolve(x)
  }, 500))
}

async function test () {
  console.log('b')
  const x = 3 + 5
  console.log(x)

  const [a, b] = await Promise.all([
    asyncGet(1),
    asyncGet(2)
  ])

  console.log('c')  
  return a + b
}

const now = Date.now()
console.log('d')
test().then(x => {
  console.log(x)
  console.log(`elapsed: ${Date.now() - now}`)
})
console.log('f')

输出效果

d
b
8
f
a
a
c
3
elapsed: 509

注重到elapsed的差异了吗?这就是为何我们说await老是递次实行的。差别的await之间没法并行实行,想要真正的完整异步还得借助相似Promise.all如许的要领。

async函数和callback

await只能能影响直接包裹它的async函数。因而在callback函数中的await并不会挂起悉数async函数的实行。

一种罕见的毛病

async function getAll (vals) {
  return vals.map(v => await asyncGet(v))
}

这段代码有语法毛病,await并不在async函数内部。假如给map的callback加上async呢?

async function getAll (vals) {
  return vals.map(async v => await asyncGet(v))
}

这段代码虽然能实行,但另有两个题目。

  1. 返回一个Promise对象的数组,并非我们期待的value数组

  2. await只会停息map的callback,因而map完成时,不能保证asyncGet也悉数完成

准确的写法还得借助Promise.all

async function getAll (vals) {
  return Promise.all(vals.map(v => asyncGet(v)))
}

总结

从上我们能够看出,Promiseasync函数的基本,想要兴奋的运用async函数,必需对Promise有比较深切的明白。以至一些罕见的使命,仅仅依托async函数没法完成。
愿望人人看完本文后能对async函数有个更周全的熟悉,如许运用起来才会越发随手。

    原文作者:BetaRabbit
    原文地址: https://segmentfault.com/a/1190000008617167
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞