async 和 await 是 ES2016 新增的两个关键字,它们借鉴了 ES2015 中生成器在实际开发中的应用,目的是简化 Promise api 的使用,并非是替代 Promise 。
async
目的是简化在函数中对 Promise 的创建。
async 用于修饰函数(无论是函数字面量还是函数表达式),放置在函数最开始的位置,被修饰函数的返回结果一定是 Promise 对象。
async function test1() {
console.log(1);
return 2;
}
const pro = test1();
console.log(pro);
// 等效于
function test() {
return new Promise((resolve, reject) => {
console.log(1);
resolve(2);
})
}
const pro1 = test();
console.log(pro1);
await
await关键字必须出现在async函数中。
await 用在某个表达式之前,如果表达式是一个 Promise,则得到的是thenable中的状态数据。
async function test1() {
console.log(1);
return 2;
}
async function test2() {
const result = await test1();
console.log(result); // 2
}
test2();
等效于:
function test3() {
return new Promise((resolve, reject) => {
console.log(111);
resolve(2);
})
}
async function test4() {
return new Promise((resolve, reject) => {
test3().then(data => {
const result = data;
console.log("test3", result); // test3 2
resolve();
})
})
}
test4();
例子1:
<script src="./封装ajax/ajax.js"></script>
<script>
async function getTeacher() {
const stus = await ajax({
url: "./回调地狱问题/json/students.json"
})
let cid;
for(let i = 0; i < stus.length; i ++) {
if(stus[i].name === "李") {
cid = stus[i].classId;
}
}
const cls = await ajax({
url: "./回调地狱问题/json/classes.json"
})
let tid;
for(let i = 0; i < cls.length; i ++) {
if(cls[i].id === cid) {
tid = cls[i].teacherId;
}
}
const ts = await ajax({
url: "./回调地狱问题/json/teachers.json"
})
// let tid;
for(let i = 0; i < ts.length; i ++) {
if(ts[i].id === tid) {
console.log(ts[i]);
}
}
console.log(stus, cid, tid)
}
getTeacher();
console.log(123);
</script>
例子2:
function biaobai(god) {
return new Promise(resolve => {
console.log(`张三向${god},发出了表白短信`);
setTimeout(() => {
if (Math.random() < 0.3) {
// 同意
resolve(true);
} else {
resolve(false);
}
}, 500)
})
}
async function biaobaiAll() {
const gods = ["女神1", "女神2", "女神3", "女神4"];
for(let i = 0; i < gods.length; i ++) {
const g = gods[i];
// 当前循环等待的 Promise 没有 resolve,下一次循环不运行
const result = await biaobai(g);
if(result) {
console.log(`${g}同意了,不用再表白了`);
break;
}else{
console.log(`${g}没有同意。`);
}
}
}
biaobaiAll();
如果 await 的表达式不是 Promise ,则会将其使用 Promise.resolve 包装后按照规则运行。
async function test() {
const result = await 1;
console.log(result);
}
test();
// 等价于
function test1() {
return new Promise((resolve, reject) => {
Promise.resolve(3).then(data => {
const result = data;
console.log(result);
})
})
}
test1();
console.log(233);
async function getPromise() {
if(Math.random() < 0.5) {
return 1;
}else{
throw 2;
}
}
async function test() {
try {
const result = await getPromise();
console.log("正常状态",result);
}catch (err) {
console.log("错误状态", err);
}
}
test();
模拟setTimeout
function delay(duration) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
},duration);
})
}
async function biaobai(god) {
console.log(`向${god}表白`);
await delay(500);
// if(Math.random() < 0.3) {
// return true;
// }else{
// return false;
// }
return Math.random() < 0.3;
}
async function biaobaiAll() {
const gods = ["女神1", "女神2", "女神3", "女神4"];
for(let i = 0; i < gods.length; i ++) {
const g = gods[i];
// 当前循环等待的 Promise 没有 resolve,下一次循环不运行
const result = await biaobai(g);
if(result) {
console.log(`${g}同意了,不用再表白了`);
break;
}else{
console.log(`${g}没有同意。`);
}
}
}
biaobaiAll();