ES6+给JavaScript带来的变化集中在变量声明、函数写法、解构赋值、模块系统和异步组织方式。围绕箭头函数、Promise、async/await和错误处理,原文给出了一组可直接运行的示例。下面按代码实现、参数语义、错误原因和适用场景重新组织,便于在脚本开发和前后端联调中复用。
一、箭头函数、解构与参数处理- const add = (a, b) => a + b;
- const square = x => x * x;
- const greet = ({ name, age }) => {
- return `Hello ${name}, you are ${age} years old`;
- };
- const user = { name: 'Alice', age: 30, city: 'Beijing' };
- const { name, age } = user;
- const numbers = [1, 2, 3, 4, 5];
- const [first, second, ...rest] = numbers;
- const { city = 'Shanghai' } = user;
- function printUser({ name, age }) {
- console.log(`${name}: ${age}`);
- }
复制代码 上述代码中,add和square利用箭头函数省略return;greet通过参数解构直接取得name和age;对象解构可配合默认值,数组解构用...rest收集剩余元素;printUser展示函数参数解构。落地时应注意:默认值只在对应属性为undefined时生效,const适合不需要重新赋值的配置和引用。
二、Promise链式调用与并发结果处理- const fetchData = () => {
- return new Promise((resolve, reject) => {
- setTimeout(() => {
- const data = { id: 1, name: 'test' };
- resolve(data);
- }, 1000);
- });
- };
- fetchData()
- .then(data => {
- console.log('Data:', data);
- return data.id;
- })
- .then(id => {
- console.log('ID:', id);
- })
- .catch(error => {
- console.error('Error:', error);
- });
- const promise1 = fetchData();
- const promise2 = fetchData();
- Promise.all([promise1, promise2])
- .then(results => {
- console.log('All results:', results);
- });
- Promise.allSettled([promise1, promise2])
- .then(results => {
- results.forEach(result => {
- if (result.status === 'fulfilled') {
- console.log('Success:', result.value);
- } else {
- console.log('Failed:', result.reason);
- }
- });
- });
复制代码 fetchData用setTimeout在1秒后resolve一个对象,用于模拟异步数据。链式then中返回data.id后,下一个then才能拿到id;catch统一接收链上前面的异常。Promise.all等待全部成功,适合多个请求都成功才继续的场景。Promise.allSettled不会因为单项失败而丢失其他结果,遍历时按status区分fulfilled和rejected,分别读取value或reason。排查时先确认then中是否return了后续需要的数据,再检查catch是否被过早吞掉。
三、async/await与HTTP错误处理- async function getUserData(userId) {
- try {
- const response = await fetch(`/api/users/${userId}`);
- const user = await response.json();
- const postsResponse = await fetch(`/api/users/${userId}/posts`);
- const posts = await postsResponse.json();
- return { ...user, posts };
- } catch (error) {
- console.error('Error:', error);
- throw error;
- }
- }
- async function processUsers() {
- try {
- const users = await Promise.all([
- getUserData(1),
- getUserData(2),
- getUserData(3)
- ]);
- console.log('All users:', users);
- } catch (error) {
- console.error('Failed to get users:', error);
- }
- }
- const fetchAndProcess = async () => {
- const data = await fetchData();
- return processData(data);
- };
- async function safeFetch(url) {
- try {
- const response = await fetch(url);
- if (!response.ok) {
- throw new Error(`HTTP error! status: ${response.status}`);
- }
- return await response.json();
- } catch (error) {
- console.error('Fetch failed:', error);
- throw error;
- }
- }
复制代码 getUserData按顺序await用户与文章请求;processUsers用Promise.all并发三个用户;async箭头函数保持与普通async函数一致的Promise返回特征。fetch请求在HTTP 4xx/5xx时不会自动进入catch,safeFetch用response.ok判断并抛出Error,这是原文错误处理代码的关键点。safeFetch先检查response.ok,非成功状态抛出带status的Error,再由catch打印并继续throw,调用方仍能感知失败。排查顺序建议:先看response.ok和status,再看catch中的error;并发场景看Promise.all外层catch;JSON解析失败也会进入catch。
四、对比与兼容性细节
异步模式对比:回调可读性低、错误处理困难、并发处理困难;Promise可读性中,错误处理用链式catch,并发用Promise.all;async/await可读性高,错误处理用try/catch,并发仍用Promise.all。变量声明对比:var是函数作用域、可重复声明、存在提升;let和const是块级作用域、不可重复声明、存在暂时性死区。模块系统对比:CommonJS静态分析否、树摇优化困难、浏览器需要打包;ES Modules静态分析是、树摇容易、浏览器原生支持。由此带来的工程影响是,ES Modules更利于静态分析和按需打包,但项目仍需结合浏览器兼容和构建流程;const优先可减少意外重赋值,需要变更引用时再用let。
五、代码风格与复用建议
const优先,箭头函数保持简洁,解构参数给出默认值。- const PI = 3.14159;
- const config = { timeout: 5000 };
- const numbers = [1, 2, 3];
- const doubled = numbers.map(n => n * 2);
- function createUser({ name, email, age = 18 }) {
- return { name, email, age };
- }
复制代码 这些写法与原文最佳实践一致:异步错误处理用try/catch或catch兜底,并发任务用Promise.all,若需要全部结果则用Promise.allSettled。原文总结中强调async/await是异步编程首选、const优先于let、ES Modules是趋势、Promise.all适合并发;在实际脚本中应结合错误边界和返回值的传递顺序使用。 |