跟着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')
async
函数和一般函数一样按递次实行,同时,在实行到await
语句时,返回一个Promise
对象await
能够明白为将async
函数挂起,直到守候的Promise
被fulfill或许reject,再继承实行以后的代码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))
}
这段代码虽然能实行,但另有两个题目。
返回一个
Promise
对象的数组,并非我们期待的value数组await
只会停息map
的callback,因而map
完成时,不能保证asyncGet
也悉数完成
准确的写法还得借助Promise.all
async function getAll (vals) {
return Promise.all(vals.map(v => asyncGet(v)))
}
总结
从上我们能够看出,Promise
是async
函数的基本,想要兴奋的运用async
函数,必需对Promise
有比较深切的明白。以至一些罕见的使命,仅仅依托async
函数没法完成。
愿望人人看完本文后能对async
函数有个更周全的熟悉,如许运用起来才会越发随手。