es6 - 看这个就够了- 超级重要! async 与 await的使用。promise.then的升级版
访问量: 1631
参考;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();
上面的代码看起来比较乱,看这个简单版