es6 - 看这个就够了- 超级重要! async 与 await的使用。promise.then的升级版
访问量: 1668
参考;http://es6.ruanyifeng.com/#docs/async
我们可以认为async+ await是 promise..then的升级版。
想使用 async + await, 一定要先知道 promise . then ..的用法(看下面)
总结:
1. async用来修饰function ,
2. await 只能用在 async 函数中, 用来声名该statement是个异步操作。(顺序执行)
3. 所有写在 async函数中的语句(无论是否是await),都是一行一行代码顺序执行的。
4. async 函数调用的 await语句必须是个return new Promise()的函数,并且,在new Promise( (resolve) ) 中要 指定resolve是啥,
new Promise().then的用法:
// Promise 有三种状态: resove (正常) , reject (出错) , pending ( 运行中)
let result = new Promise( (resolve, reject ) => {
let result = 0
setTimeout( () => {
console.info("sleep n ms...")
result = 200
resolve(result) // 注意,这里的 resolve, 就相当于是返回了。
}, 3000)
})
// 运行
result.then( (temp) => {
console.info("result : ", temp)
})
下面是个超级简单的例子: (async, await , 与 Promise()一起使用)
// 注意这里是普通函数
function sleep() {
// 注意这里要return
return new Promise( (resolve) => {
setTimeout(() => {
resolve("abc") // 注意这里必须要 resolve
}, 1500)
})
}
// 注意: 这里使用了 async.
async function get_result_after_sleep(){
console.info("== now in get_result_after_sleep")
let result = await sleep() // 这里要获得 result, 就是 sleep()函数中的 resolve() 出来的结果
console.info("== result: ", result)
}
get_result_after_sleep()
我们看一个 例子(promise + then)
function delayedPrint(time){
console.info( (Date.now() / 1000) + "== 延迟 "+ time + "ms 后开始打印")
return new Promise( resolve => {
setTimeout( () =>{
resolve(time + 500)
}
,time)
})
}
delayedPrint(2000).then( () => {
console.info((Date.now() / 1000) + "== hello!")
})
运行结果:
1545636482.144== 延迟 2000ms 后开始打印 1545636484.148== hello!
可以把上面的代码写成:
function delayedPrint(time){
console.info( (Date.now() / 1000) + "== 延迟 "+ time + "ms 后开始打印")
return new Promise( resolve => {
setTimeout( () =>{
resolve(time + 500)
}
,time)
})
}
// 定义了一个封装后的方法: async ...
async function print(){
// 调用该方法时, 传入一个参数就好了。resolver 不用传
await delayedPrint(2000)
// 这一行代码就是resolver的实现
console.info((Date.now() / 1000) + "== hello!")
}
// 最后,调用这个 async方法
print()
效果是一样的。
$ node test_async.js 1545636670.899== 延迟 2000ms 后开始打印 1545636672.902== hello!
为什么使用它。
回答: 为了避免 callback hells (回调地狱)。(参考https://segmentfault.com/a/1190000007535316) 我们看下面的代码:
function step1(n) {
console.log(`step1 with ${n}`);
return takeLongTime(n);
}
function step2(m, n) {
console.log(`step2 with ${m} and ${n}`);
return takeLongTime(m + n);
}
function step3(k, m, n) {
console.log(`step3 with ${k}, ${m} and ${n}`);
return takeLongTime(k + m + n);
}
上面的代码中,每一步的参数,都是上一次的结果, 例如 step2的参数 之一是step1的结果。 step3的参数是step2, step1的结果。如果用promise then来写的话:
function doIt() {
console.time("doIt");
const time1 = 300;
step1(time1)
.then(time2 => {
return step2(time1, time2)
.then(time3 => [time1, time2, time3]);
})
.then(times => {
const [time1, time2, time3] = times;
return step3(time1, time2, time3);
})
.then(result => {
console.log(`result is ${result}`);
console.timeEnd("doIt");
});
}
doIt();
可以看出非常麻烦, 但是用 await/async来写就特别舒服
async function doIt() {
console.time("doIt");
const time1 = 300;
const time2 = await step1(time1);
const time3 = await step2(time1, time2);
const result = await step3(time1, time2, time3);
console.log(`result is ${result}`);
console.timeEnd("doIt");
}
doIt();
上面的代码看起来比较乱,看这个简单版