async 和 await 是 ES2016 新增两个关键字,它们借鉴了 ES2015 中生成器在实际开发中的应用,目的是简化 Promise api 的使用,并非是替代 Promise。
一、async
目的是简化在函数的返回值中对Promise的创建
async 用于修饰函数(无论是函数字面量还是函数表达式),放置在函数最开始的位置,被修饰函数的返回结果一定是 Promise 对象。
async function test(){
console.log(1);
return 2;
};
//等效于
function test(){
return new Promise((resolve, reject)=>{
console.log(1);
resolve(2);
})
};
async function test() {
console.log(1);
return 5;
};
const pro = test();
pro.then(result=>{
console.log(result);
});
如果需要推向rejected
async function test() {
console.log(1);
throw 5;
};
const pro = test();
pro.then(result=>{
console.log(result);
});
二、await
await关键字必须出现在async函数中!!!!
await用在某个表达式之前,如果表达式是一个Promise,则得到的是thenable中的状态数据。
async function test1(){
console.log(1);
return 2;
}
async function test2(){
const result = await test1();
console.log(result);
}
test2();
//等效于
function test1(){
return new Promise((resolve, reject)=>{
console.log(1);
resolve(2);
})
};
function test2(){
return new Promise((resolve, reject)=>{
test1().then(data => {
const result = data;
console.log(result);
resolve();
})
})
};
test2();
async function test1() {
console.log(1);
return 2;
};
async function test2() {
const result = await test1();//等待test1完成
console.log(result);
throw 3;
};
async function test3(){
const err = await test2();
console.log(err);
};
test3();
三、实例
如果需要推向rejected报错但不影响后续执行,则使用try…catch
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();
原问题1:通过查询到的信息寻找后面的信息,导致一直回调
//获取李华所在班级的老师的信息
//1. 获取李华的班级id Promise
//2. 根据班级id获取李华所在班级的老师id Promise
//3. 根据老师的id查询老师信息 Promise
ajax({//这里通过封装会直接返回请求到的json数据
url: "./data/students.json?name=李华",
success: function(data) {
for (let i = 0; i < data.length; i++) {
if (data[i].name === "李华") {
const cid = data[i].classId;
ajax({
url: "./data/classes.json?id=" + cid,
success: function(data) {
for (let i = 0; i < data.length; i++) {
if (data[i].id === cid) {
const tid = data[i].teacherId;
ajax({
url: "./data/teachers.json?id=" + tid,
success: function(data) {
for (let i = 0; i < data.length; i++) {
if (data[i].id === tid) {
console.log(data[i]);
}
}
}
})
return;
}
}
}
})
return;
}
}
}
});
现解决
//获取李华所在班级的老师的信息
//1. 获取李华的班级id Promise
//2. 根据班级id获取李华所在班级的老师id Promise
//3. 根据老师的id查询老师信息 Promise
async function getTeacher() {
const stus = await ajax({
url: "./data/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: "./data/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: "./data/teachers.json"
})
for (let i = 0; i < ts.length; i++) {
const element = ts[i];
if (element.id === tid) {
console.log(element);
}
}
};
getTeacher();
原问题2:表白问题
function biaobai(god, callback) {
console.log(`我向女神【${god}】发出了表白短信`);
setTimeout(() => {
if (Math.random() < 0.1) {
//女神同意拉
//resolve
callback(true);
} else {
//resolve
callback(false);
}
}, 1000);
};
biaobai("女神1", function(result) {
if (result) {
console.log("女神1答应了!")
} else {
console.log("女神1拒绝了,没事,向女神2表白");
biaobai("女神2", function(result) {
if (result) {
console.log("女神2答应了!")
} else {
console.log("女神2十分感动,然后拒绝了,向女神3表白");
biaobai("女神3", function(result) {
if (result) {
console.log("女神3答应了!")
} else {
console.log("表示生无可恋!!");
}
});
}
});
}
});
现解决
function biaobai(god) {
return new Promise(resolve => {
console.log(`邓哥向${god}发出了表白短信`);
setTimeout(() => {
if (Math.random() < 0.3) {
//女神同意拉
resolve(true)
} else {
//resolve
resolve(false);
}
}, 500);
})
};
(async () => {
const gods = ["女神1", "女神2", "女神3", "女神4", "女神5"];
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}没有同意`)
}
}
})()
四、改造计时器
因为定时器是老API,所以我们想直接利用定时器return 而不是resolve返回到的是外界函数而不是给async 接收,这里对定时器进行优化。
function delay(duration) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, duration);
})
};
async function biaobai(god) {
console.log(`我向${god}发出了表白短信`);
await delay(500);
return Math.random() < 0.3;
};