其他相关传送门
async
是ES7新出的特性,表明当前函数是异步函数,不会阻塞线程导致后续代码停止运行。
async
函数,就是 Generator 函数 的语法糖。
相较于 Generator,async
函数的改进在于下面四点:
Generator
函数的执行必须依靠执行器,而 async
函数自带执行器,调用方式跟普通函数的调用一样async
和 await
相较于 *
和 yield
更加语义化co
模块约定,yield
命令后面只能是 Thunk
函数或 Promise
对象。而 async
函数的 await
命令后面则可以是 Promise
或者 原始类型的值(Number
,string
,boolean
,但这时等同于同步操作)async
函数返回值是 Promise
对象,比 Generator
函数返回的 Iterator
对象方便,可以直接使用 then()
方法进行调用async function asyncFn() {
console.log('这里是同步');
return '我后执行'; // 返回一个 promise 对象,相当于 return Promise.resolve('我后执行')
}
console.log(asyncFn()); // Promise {: "我后执行"}
asyncFn().then(result => {
console.log(result+',这里是异步');
})
console.log('我先执行');
// 这里是同步
// 我先执行
// 我后执行,这里是异步
上面的执行结果是先打印出'我先执行'
,虽然是上面asyncFn()
先执行,但是已经被定义异步函数了,不会影响后续函数的执行。
async 定义的函数内部会默认返回一个 promise 对象:
reject
,则判定成功,这里可以return
各种数据类型的值,false
,NaN
,undefined
…总之,都是resolve
reject
,都会使函数的promise
状态为失败reject
在async
里,必须要将结果return
出去,不然的话不管是执行reject
还是resolved
的值都为undefine
//正确reject方法。必须将reject状态return出去。
async function PromiseError() {
return Promise.reject('has Promise Error');
}
//这是错误的做法,并且判定resolve,返回值为undefined,并且Uncaught报错
async function PromiseError() {
Promise.reject('这是错误的做法');
}
await
意思是 async wait
(异步等待)。
await
后面接一个会 return new promise
的函数并执行它await
只能放在 async
函数里任何 async
函数都会默认返回 promise
,并且这个 promise
解析的值都将会是这个函数的返回值,而 async
函数必须等到内部所有的 await
命令的 Promise
对象执行完,才会发生状态改变。
就是说,必须等所有await
函数执行完毕后,才会告诉promise
我成功了还是失败了,执行then
或者catch
function dice(){
return new Promise((resolve, reject)=>{
let sino = parseInt(Math.random() * 6 +1);
setTimeout(()=>{
resolve(sino);
},3000);
})
}
async function test(){
let n =await dice(); // await 相当于 Promise 的 then
console.log(n);
}
test();
把await
和成功后的操作放到try
里,失败的放在catch
:
function dice(val) {
return new Promise((resolve, reject) => {
let sino = parseInt(Math.random() * 6 + 1);
if (sino > 3) {
val === '大' ? resolve(sino) : reject(sino);
} else {
val === '大' ? reject(sino) : resolve(sino);
}
})
}
async function test() {
// try...catch 可捕获异常,代替了 Promise 的 catch
try {
//把await及获取它的值的操作放在try里
let n = await dice('大'); // await 相当于 Promise 的 then
console.log('赢了' + n);
} catch (error) {
//失败的操作放在catch里
console.log('输了' + error); // 相当于 Promise 的 catch
}
}
test();
await 后面是 rejected 状态的栗子:
(async function () {
const p = Promise.reject('promise error');
const res = await p; // await 相当于 Promise 的 then, 但这里是rejected状态,会报错
console.log(res);
})()
用 try...catch
捕获异常即可:
(async function () {
const p = Promise.reject('promise error');
try {
const res = await p;
console.log(res);
} catch (error) {
console.log(error); // 正常输出: promise error
}
})()
await 下面所有的代码都是异步
await
等到的结果分2种:
async function async1() {
await async2(); // 先执行async2(),await下面所有的代码都是异步
console.log(1); // 异步
}
async function async2() {
console.log(2);
}
console.log(3);
async1();
// 3
// 2
// 1
function fn() {
return new Promise(resolve => {
console.log(1); // 同步2
resolve();
})
}
async function async1() {
await fn().then(() => { // 先执行fn(),await下面所有的代码都是异步
console.log(2); // 异步1
})
console.log(3); // 异步1的下一个异步
}
console.log(4); // 同步1
async1();
// 4
// 1
// 2
// 3
如果asycn里的代码都是同步的,那么这个函数被调用就会同步执行
async function fn(){
console.log('a'); // 同步1
}
fn();
console.log('b'); // 同步2
//a
//b
async function async1() {
console.log(1); // 同步2
await async2(); // 先执行async2() 再await
console.log(2); // 异步(await下面所有的代码都是异步)
}
async function async2() {
console.log(3); // 同步3
}
console.log(4); // 同步1
async1();
console.log(5); // 同步4
// 4
// 1
// 3
// 5
// 2
async function async1() {
console.log(1);
await async2();
console.log(2);
await async3();
console.log(3);
}
async function async2() {
return new Promise((resolve) => {
console.log(4);
resolve(); // 如果没有resolve(),await async2()后的代码都不会执行,只输出6 1 4 7
})
}
async function async3() {
console.log(5);
}
console.log(6);
async1();
console.log(7);
// 6
// 1
// 4
// 7
// 2
// 5
// 3
相比于 Promise
,async/await
能更好地处理 then链
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);
}
使用then的链式调用
:
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}`);
});
}
doIt();
// step1 with 300
// step2 with 500
// step3 with 700
// result is 900
使用 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}`);
}
doIt();
// step1 with 300
// step2 with 500
// step3 with 700
// result is 900