JavaScript 中的 async await 是什么?
简介
异步函数使用 async
和 await
语法来等待一个 promise 被解析。为了更好地理解这篇文章,建议了解 promise 的工作原理。你可以在这里了解它们。
回调地狱
引入 async/await 的原因之一是为了避免众所周知的 "回调地狱",即函数嵌套多层。当一个函数的结果需要进一步查询和验证时,这种情况非常常见。
我们将创建一个简单的流程来举例说明 "回调地狱":
javascript
function suma(a, b, cb) {
cb(a + b); // 在回调中返回两个数的和
}
function restar(valor, cantidad, cb) {
cb(valor - cantidad); // 从一个值中减去一定数量
}
function esMayorACero(valor, cb) {
if (valor > 0) {
cb('Mayor a cero');
} else {
cb('Menor a cero');
}
}
const x = 10;
const y = 20;
// 如果有更多的派生流程,它会嵌套得越来越深
suma(x, y, function (resultado_de_suma) {
// 结果:30
restar(resultado_de_suma, 15, function (resultado_de_resta) {
// 结果:15
esMayorACero(resultado_de_resta, function (respuesta) {
// 结果:'Mayor a cero'
console.log(respuesta); // Mayor a cero
});
});
});
这是一个有代表性的例子,因为回调最常用于服务器请求等异步过程。
Promise
为了重写前面的例子,我们将把函数转换为 promise:
javascript
function suma(a, b) {
return new Promise(function (resolve, reject) {
resolve(a + b);
});
}
function restar(valor, cantidad) {
return new Promise(function (resolve, reject) {
resolve(valor - cantidad);
});
}
function esMayorACero(valor) {
return new Promise(function (resolve, reject) {
if (valor > 0) {
resolve('Mayor a cero');
} else {
resolve('Menor a cero');
}
});
}
const x = 10;
const y = 20;
suma(x, y)
.then(function (resultado_de_suma) {
// 结果:30
return restar(resultado_de_suma, 15);
})
.then(function (resultado_de_resta) {
// 结果:15
return esMayorACero(resultado_de_resta);
})
.then(function (respuesta) {
// 结果:'Mayor a cero'
console.log(respuesta);
});
通过返回一个 promise,我们可以在它们被解析时链式调用 then()
。
Async/Await
现在我们将使用 async/await 重写这个例子。由于它与 promise 一起工作,我们将使用上一个代码中声明的相同函数。
Async/Await 只能在异步函数中工作,即语法为 async function function_name () {}
的函数。
javascript
const x = 10;
const y = 20;
// 带有 "async" 的异步函数
async function mayorACero() {
try {
let resultado_de_suma = await suma(x, y); // 结果:30
let resultado_de_resta = await restar(resultado_de_suma, 15); // 结果:15
let respuesta = await esMayorACero(resultado_de_resta); // 结果:'Mayor a cero'
console.log(respuesta);
} catch (err) {
// 错误处理
}
}
mayorACero(); // 结果:'Mayor a cero'
如果我们在 async
函数之外使用 await
语法,就会导致错误。
得益于 async/await,我们可以以更加顺序化的方式处理异步函数,为我们的代码提供更多的清晰度。
当使用 await
时,建议将其放在 try {} catch() {}
中,以便在 catch() {}
中能够控制失败的 promise。这是因为如果一个 promise 在 try
中失败,错误将传播到 catch
块。
因为 async/await 相对较新,建议谨慎使用,因为它不能在 IE11 等旧浏览器中工作。你可以在这里查看它的支持情况。
我希望这篇文章能帮助你熟悉 ECMAScript7 中的一些新特性,在本例中是 async/await。