JavaScript 异步编程:理解 `await` 和 `Promise`
在现代 JavaScript 开发中,处理异步操作是较为常见的需求。但 Javascript 具有多种异步模型,本文主要研究在云函数开发中常用的 await
和 Promise
两种异步范式,以便于更好地理解异步机制。
Promise 的基础知识
Promise
是一个表示异步操作结果的对象,它有三种状态:
- Pending(待定): 初始状态,异步操作还在进行中。
- Fulfilled(已完成): 异步操作成功完成,
Promise
的结果可用。 - Rejected(已拒绝): 异步操作失败,
Promise
的结果是错误信息。
创建一个 Promise:
const promise = new Promise((resolve, reject) => {
// 模拟异步操作
setTimeout(() => {
const success = true; // 模拟成功或失败
if (success) {
resolve("Operation succeeded");
} else {
reject("Operation failed");
}
}, 1000);
});
处理 Promise 的结果:
promise
.then((result) => {
console.log(result); // 输出: "Operation succeeded"
})
.catch((error) => {
console.error(error); // 输出: "Operation failed"
});
async 和 await 的作用
async
和 await
是现代 JavaScript 用来简化异步编程的语法糖。它们使异步代码看起来像同步代码,使得处理异步操作更为直观。
定义 async
函数:
一个 async
函数总是返回一个 Promise
。如果函数内有返回值,它会被自动包装为 Promise.resolve()
;如果抛出异常,则会被包装为 Promise.reject()
。
async function fetchData() {
return "Data fetched";
}
使用 await
:
await
用来暂停 async
函数的执行,直到 Promise
被解决或拒绝。它可以让异步操作的代码更像同步代码,易于阅读和维护。
async function fetchData() {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return data;
}
示例:
async function processFiles() {
try {
console.log('Start processing files');
const file1 = await fetchData('/path/to/file1');
console.log('File 1:', file1);
const file2 = await fetchData('/path/to/file2');
console.log('File 2:', file2);
const file3 = await fetchData('/path/to/file3');
console.log('File 3:', file3);
console.log('All files processed');
} catch (error) {
console.error('Error processing files:', error);
}
}
processFiles();
Promise 的静态方法
-
Promise.resolve(value)
:- 返回一个以给定值解析的
Promise
。如果值是一个Promise
,则返回这个Promise
。
Promise.resolve('Success').then(console.log);
- 返回一个以给定值解析的
-
Promise.reject(reason)
:- 返回一个以给定拒绝原因拒绝的
Promise
。
Promise.reject('Error').catch(console.error);
- 返回一个以给定拒绝原因拒绝的
-
Promise.all(iterable)
:- 接受一个可迭代对象(如数组),其中的每个元素都是
Promise
。 - 返回一个新的
Promise
,在所有输入的Promise
完成后解析。 - 如果任何
Promise
被拒绝,返回的Promise
也会被拒绝。
Promise.all([p1, p2, p3]) .then(results => console.log(results)) .catch(error => console.error(error));
- 接受一个可迭代对象(如数组),其中的每个元素都是
-
Promise.allSettled(iterable)
:- 与
Promise.all
类似,但不管所有Promise
的状态如何,都返回一个Promise
。 - 解析的值是一个数组,每个元素都是一个对象,表示每个
Promise
的状态和结果。
Promise.allSettled([p1, p2, p3]) .then(results => results.forEach(result => console.log(result)));
- 与
-
Promise.any(iterable)
:- 接受一个可迭代对象,其中的每个元素都是
Promise
。 - 返回一个新的
Promise
,在第一个成功的Promise
解决时解析。 - 如果所有
Promise
都被拒绝,则返回一个AggregateError
。
Promise.any([p1, p2, p3]) .then(result => console.log(result)) .catch(error => console.error(error));
- 接受一个可迭代对象,其中的每个元素都是
-
Promise.race(iterable)
:- 接受一个可迭代对象,其中的每个元素都是
Promise
。 - 返回一个新的
Promise
,在第一个Promise
解决或拒绝时解析或拒绝。
Promise.race([p1, p2, p3]) .then(result => console.log(result)) .catch(error => console.error(error));
- 接受一个可迭代对象,其中的每个元素都是
Promise 的组合
.finally()
:- 在
Promise
被解决或拒绝后执行,无论结果如何都会执行finally
中的代码。 - 用于清理操作,例如关闭资源或重置状态。
promise .then(result => console.log(result)) .catch(error => console.error(error)) .finally(() => console.log('Operation completed'));
- 在
参考
- 浅谈浏览器多进程与 JS 线程
- 浏览器的线程有哪些
- 一次搞懂-JavaScript之异步编程
- 一次搞懂-JS 事件循环之宏任务和微任务
- 深入理解事件循环,这一篇就够了
- Tasks, microtasks, queues and schedules
- Python 最强异步编程:Asyncio
- Golang异步编程方式和技巧
Comments
Leave a comment