async/await 函数
1. async函数的原理
async函数在本质上是基于Promise实现的,所以先要理解promise和JavaScript 异步操作
JavaScript 异步操作:
JavaScript 是单线程的,它通过 事件循环(Event Loop) 来处理异步操作。通常,异步操作不会阻塞主线程,而是通过将回调函数放入事件队列来等待执行。这种机制使得 JavaScript 能够同时处理多个任务,而不会阻塞 UI 或其他操作。
Promise
的工作原理
Promise
是一种表示异步操作最终完成或失败的机制。它有三种状态:
- Pending:初始状态,表示操作尚未完成。
- Resolved/Fulfilled:表示操作完成并返回了成功的结果。
- Rejected:表示操作失败并返回了错误。
Promise
的常见用法是通过 .then()
和 .catch()
来处理异步操作的结果:
fetch('https://api.example.com/data').then(response => response.json()).then(data => console.log(data)).catch(error => console.error(error));
Promise之所以可以解决回调地狱就是因为promise是个对象,而他的回调函数是附加在promise上的,所以遇到回调地狱问题我们就可以用promise链式调用来解决它,它可以从回调函数的层层包含中跳出来
async/await
是在 Promise
的基础上简化了异步编程的工具。
async
函数本质上是返回一个 Promise
的函数,即使你没有显式地返回 Promise
,它也会自动将函数的返回值封装为一个 Promise
。这使得异步函数看起来更像同步代码,减少了传统异步操作中对 .then()
的需求。当一个函数被声明为 async
时,内部会自动有一个隐式的 Promise
:
async function example() {return "Hello, World!";
}example().then(result => console.log(result)); // "Hello, World!"
await
await
操作符用于等待一个 Promise 兑现并获取它兑现之后的值。它只能在异步函数或者模块顶层中使用。当他后面跟着promise对象的时候,他会暂停异步代码等待promise执行完然后返回其兑现的值,如果是一个非promise,那么就会把它当作是已经兑现的Promis,正常执行,如果promise被拒绝,返回被拒绝的原因。
function resolveAfter2Seconds(x) {return new Promise((resolve) => {setTimeout(() => {resolve(x);}, 2000);});
}async function f1() {let x = await resolveAfter2Seconds(10);console.log(x); // 10
}f1();
当函数执行到 await
时,被等待的表达式会立即执行,所有依赖该表达式的值的代码会被暂停,并推送进微任务队列(microtask queue)。然后主线程被释放出来,用于事件循环中的下一个任务。即使等待的值是已经敲定的 promise 或不是 promise,也会发生这种情况
以下示例代码来自mdn
async function foo(name) {console.log(name, "start");await console.log(name, "middle");console.log(name, "end");
}foo("First");
foo("Second");// First start
// First middle
// Second start
// Second middle
// First end
// Second end
用promise写相当于
function foo(name) {return new Promise((resolve) => {console.log(name, "start");resolve(console.log(name, "middle"));}).then(() => {console.log(name, "end");});
}