async/await
Async/Await
理解的还是不透彻,只是抄录了别人的文章。。。。。
async
ES2017 标准引入了 async 函数,使得异步操作变得更加方便。
async 函数是什么?一句话,它就是 Generator 函数的语法糖。
async 函数返回一个 Promise 对象
,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
(async function () {
return '我是Promise'
})()
// 返回是Promise
//Promise {<resolved>: "我是Promise"}
你会发现返回是这个:Promise {
自动解析成 Promise.resolve(‘我是Promise’);
等同于:
(async function () {
return Promise.resolve('我是Promise');
})()
所以你想像一般function的返回那样,拿到返回值,原来的思维要改改了!你可以这样拿到返回值:
const demo = async function () {
return Promise.resolve('我是Promise');
// 等同于 return '我是Promise'
// 等同于 return new Promise((resolve,reject)=>{ resolve('我是Promise') })
}
demo.then(result=>{
console.log(result) // 这里拿到返回值
})
demo
async function timeout( ) {
return 'hello world'
}
timeout();
console.log('虽然在后面,但是我先执行');
async function testAsync( ) {
return 'hello async';
}
testAsync().then((v) => {
console.log(v); // 输出 "hello async"
});
如果 async 函数没有返回值,它会返回 Promise.resolve(undefined)。
await
await 命令只能用在 async 函数之中
,如果用在普通函数,就会报错。
async 函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而 await 命令就是内部 then 命令的语法糖。
await 的本质是可以提供等同于”同步效果“的等待异步返回能力的语法糖
。
await 表达式会 暂停
当前 async function 的执行,等待 Promise 处理完成。若 Promise 正常处理(fulfilled),其回调的resolve 函数参数作为 await 表达式的值,继续执行 async function。
await 休眠效果
JavaScript 一直没有休眠的语法,但是借助await命令就可以让程序停顿指定的时间。
function sleep(interval) {
return new Promise(resolve => {
setTimeout(resolve, interval);
})
}
// 用法
async function one2FiveInAsync() {
for(let i = 1; i <= 5; i++) {
console.log(i);
await sleep(1000);
}
}
one2FiveInAsync();
async/await 的优势
优势在于处理 then 链
假设一个业务,分多个步骤完成,每个步骤都是异步的,而且依赖于上一个步骤的结果。
/** * 传入参数 n,表示这个函数执行的时间(毫秒) * 执行的结果是 n + 200,这个值将用于下一步骤 */
function takeLongTime(n) {
return new Promise(resolve => {
setTimeout(() => resolve(n + 200), n);
});
}
function step1(n) {
console.log(`step1 with ${n}`);
return takeLongTime(n);
}
function step2(n) {
console.log(`step2 with ${n}`);
return takeLongTime(n);
}
function step3(n) {
console.log(`step3 with ${n}`);
return takeLongTime(n);
}
现在用 Promise 方式来实现这三个步骤的处理
function doIt( ) {
console.time('doIt');
const time1 = 300;
step1(time1)
.then(time2 => step2(time2))
.then(time3 => step3(time3))
.then(result => {
console.log(`result is ${result}`);
console.timeEnd('doIt');
});
}
doIt();
// step1 with 300
// step2 with 500
// step3 with 700
// result is 900
// doIt: 1503.638916015625ms
如果用 async/await 来实现呢,会是这样:
async function doIt( ) {
console.time('doIt');
const time1 = 300;
const time2 = await step1(time1);
const time3 = await step2(time2);
const result = await step3(time3);
console.log(`result is ${result}`);
console.timeEnd('doIt');
}
doIt();
async/await 执行顺序题
async function async1( ){
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2( ){
console.log('async2');
}
async1();
console.log('i am koala');
正确的执行顺序
"async1 start"
"async2"
"i am koala"
"async1 end"
执行到 async1 这个函数时,首先会打印出 “async1 start”(async 表达式定义的函数也是立即执行的);
await async2(),发现 async2 也是个 async 定义的函数,所以直接执行了“console.log(‘async2’)”,同时async2返回了一个Promise,划重点:此时返回的Promise会被放入到回调队列中等待,await会让出线程(js是单线程还用我介绍吗),接下来就会跳出 async1函数 继续往下执行。
promise、async和await的执行顺序
async function async1(){
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2(){
console.log('async2')
}
console.log('script start')
setTimeout(function(){
console.log('setTimeout')
},0)
async1();
new Promise(function(resolve){
console.log('promise1')
resolve();
}).then(function(){
console.log('promise2')
})
console.log('script end')
正确答案
script start
async1 start
async2
promise1
script end
promise2
async1 end
setTimeout
知识点
显然,这考察的是 js 中的事件循环和回调队列。注意以下几点:
- Promise 优先于s etTimeout 宏任务。所以,setTimeout 回调会在最后执行。
- Promise 一旦被定义,就会立即执行。
- Promise 的 reject 和 resolve 是异步执行的回调。所以,resolve() 会被放到回调队列中,在主函数执行完和 setTimeout 前调用。
- await 执行完后,会让出线程。async 标记的函数会返回一个 Promise 对象
解题
执行到 async1 这个函数时,首先会打印出“async1 start”(这个不用多说了吧,async 表达式定义的函数也是立即执行的);
然后执行到 await async2(),发现 async2 也是个 async 定义的函数,所以直接执行了“console.log(‘async2’)”,同时async2返回了一个Promise,划重点:此时返回的Promise会被放入到回调队列中等待,await会让出线程(js是单线程还用我介绍吗),接下来就会跳出 async1函数 继续往下执行。
然后执行到 new Promise,前面说过了promise是立即执行的,所以先打印出来“promise1”,然后执行到 resolve 的时候,resolve这个任务就被放到回调队列中(前面都讲过了上课要好好听啊喂)等待,然后跳出Promise继续往下执行,输出“script end”。
接下来是重头戏。同步的事件都循环执行完了,调用栈现在已经空出来了,那么事件循环就会去回调队列里面取任务继续放到调用栈里面了。
这时候取到的第一个任务,就是前面 async1 放进去的Promise,执行Promise时发现又遇到了他的真命天子resolve函数,划重点:这个resolve又会被放入任务队列继续等待,然后再次跳出 async1函数 继续下一个任务。
接下来取到的下一个任务,就是前面 new Promise 放进去的 resolve回调 啦 yohoo~这个resolve被放到调用栈执行,并输出“promise2”,然后继续取下一个任务。
后面的事情相信你已经猜到了,没错调用栈再次空出来了,事件循环就取到了下一个任务:历经千辛万苦终于轮到的那个Promise的resolve回调!!!执行它(啥也不会打印的,因为 async2 并没有return东西,所以这个resolve的参数是undefined),此时 await 定义的这个 Promise 已经执行完并且返回了结果,所以可以继续往下执行 async1函数 后面的任务了,那就是“console.log(‘async1 end’)”。
谜之困惑的那两句执行结果(“promise2”、“async1 end”)就是这样来的~
await命令放在try…catch代码块中
async function myFunction() {
try {
await somethingThatReturnsAPromise();
} catch (err) {
console.log(err);
}
}
// 另一种写法
async function myFunction() {
await somethingThatReturnsAPromise()
.catch(function (err) {
console.log(err);
});
}
more
-https://blog.csdn.net/CSDN_KONGlX/article/details/125631279