async 和 await 是 ES2016 新增的兩個關鍵字纫骑,它們借鑒了 ES2015 中生成器在實際開發(fā)中的應用,目的是簡化 Promise api 的使用吓肋,并非是替代 Promise 折剃。
async
目的是簡化在函數(shù)中對 Promise 的創(chuàng)建镶奉。
async 用于修飾函數(shù)(無論是函數(shù)字面量還是函數(shù)表達式),放置在函數(shù)最開始的位置莹捡,被修飾函數(shù)的返回結果一定是 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關鍵字必須出現(xiàn)在async函數(shù)中。
await 用在某個表達式之前篮赢,如果表達式是一個 Promise齿椅,則得到的是thenable中的狀態(tài)數(shù)據(jù)。
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}启泣,發(fā)出了表白短信`);
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];
// 當前循環(huán)等待的 Promise 沒有 resolve涣脚,下一次循環(huán)不運行
const result = await biaobai(g);
if(result) {
console.log(`${g}同意了,不用再表白了`);
break;
}else{
console.log(`${g}沒有同意寥茫。`);
}
}
}
biaobaiAll();
如果 await 的表達式不是 Promise 遣蚀,則會將其使用 Promise.resolve 包裝后按照規(guī)則運行。
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("正常狀態(tài)",result);
}catch (err) {
console.log("錯誤狀態(tài)", 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];
// 當前循環(huán)等待的 Promise 沒有 resolve纱耻,下一次循環(huán)不運行
const result = await biaobai(g);
if(result) {
console.log(`${g}同意了芭梯,不用再表白了`);
break;
}else{
console.log(`${g}沒有同意。`);
}
}
}
biaobaiAll();