JavaScript的 Promise,then 笔记250803

JavaScript的 Promise,then 笔记250803

实例讲解

例一:
例一代码:

new Promise( (resolve, reject)=>{
	resolve("resolve","的","参数");
	reject("reject","的","参","数");
}).then(
	(v0,v1,v2) => console.log(v0,v1,v2,"从then的第一个函数参数执行的输出")
	,
	(v0,v1,v2,v3) => console.log(v0,v1,v2,v3,"从then的第二个函数参数执行的输出")
).catch(
	(v0,v1,v2,v3) => console.log(v0,v1,v2,v3, "从catch的第一个函数参数执行的输出")
)

例一结果输出:

resolve undefined undefined 从then的第一个函数参数执行的输出

例一讲解

new Promise( (resolve, reject)=>{
	resolve("resolve","的","参数");        //////// 结果 "resolve undefined undefined" 反映resolve只能传递一个参数
	reject("reject","的","参","数");        //////// 没有执行, 执行了 resolve 就不会再执行 reject
}).then(
	(v0,v1,v2) => console.log(v0,v1,v2,"从then的第一个函数参数执行的输出")        //////// 输出了这条结果
	,
	(v0,v1,v2,v3) => console.log(v0,v1,v2,v3,"从then的第二个函数参数执行的输出")
).catch(
	(v0,v1,v2,v3) => console.log(v0,v1,v2,v3, "从catch的第一个函数参数执行的输出")
)

从例一看出:

  • resolve只能放入一个参数, 多余的参数不会传递下去
  • 执行resolve后, reject不会执行




例二:
例二代码: 与 例一 的唯一区别是调换了 resolvereject 的执行顺序

new Promise( (resolve, reject)=>{
	resolve("resolve","的","参数");
	reject("reject","的","参","数");
}).then(
	(v0,v1,v2) => console.log(v0,v1,v2,"从then的第一个函数参数执行的输出")
	,
	(v0,v1,v2,v3) => console.log(v0,v1,v2,v3,"从then的第二个函数参数执行的输出")
).catch(
	(v0,v1,v2,v3) => console.log(v0,v1,v2,v3, "从catch的第一个函数参数执行的输出")
)

例二结果输出:

reject undefined undefined undefined 从then的第二个函数参数执行的输出

例二讲解

new Promise( (resolve, reject)=>{
	reject("reject","的","参","数");        ////////  结果 "reject undefined undefined undefined" 反映reject只能传递一个参数
	resolve("resolve","的","参数");        //////// 没有执行, 执行了 reject 就不会再执行 resove
}).then(
	(v0,v1,v2) => console.log(v0,v1,v2,"从then的第一个函数参数执行的输出")
	,
	(v0,v1,v2,v3) => console.log(v0,v1,v2,v3,"从then的第二个函数参数执行的输出")        //////// 输出了这条结果
).catch(
	(v0,v1,v2,v3) => console.log(v0,v1,v2,v3, "从catch的第一个函数参数执行的输出")        //////// 没有执行, 因为在then的第二个参数执行过了
)

从例二看出:

  • rejectresolve一样只能放入一个参数, 多余的参数不会传递下去
  • 执行reject后, resolve不会执行
  • 如果then使用了两个参数, then的第二个函数参数执行过了,就不会再执行catch的函数参数




例三:
例三代码: 与 例二 的唯一区别是注释了then的第二个函数参数(只用一个参数),留给catch

new Promise( (resolve, reject)=>{
	resolve("resolve","的","参数");
	reject("reject","的","参","数");
}).then(
	(v0,v1,v2) => console.log(v0,v1,v2,"从then的第一个函数参数执行的输出")
	//,
	//(v0,v1,v2,v3) => console.log(v0,v1,v2,v3,"从then的第二个函数参数执行的输出")
).catch(
	(v0,v1,v2,v3) => console.log(v0,v1,v2,v3, "从catch的第一个函数参数执行的输出")
)

例三结果输出:

reject undefined undefined undefined 从catch的第一个函数参数执行的输出

例三讲解

new Promise( (resolve, reject)=>{
	reject("reject","的","参","数");        ////////  结果 "reject undefined undefined undefined" 反映reject只能传递一个参数
	resolve("resolve","的","参数");        //////// 没有执行, 执行了 reject 就不会再执行 resove
}).then(
	(v0,v1,v2) => console.log(v0,v1,v2,"从then的第一个函数参数执行的输出")
	//,
	//(v0,v1,v2,v3) => console.log(v0,v1,v2,v3,"从then的第二个函数参数执行的输出")        //////// 注释了
).catch(
	(v0,v1,v2,v3) => console.log(v0,v1,v2,v3, "从catch的第一个函数参数执行的输出")        //////// 输出了这条结果
)

从例三看出:

  • rejectresolve一样只能放入一个参数, 多余的参数不会传递下去
  • 如果先执行了reject后, resolve不会执行, 二者只能执行其一
  • 如果then只使用一个参数, reject传递到catch ; 如果then使用两参数, 那么rejectthen的参数2截胡, 不会传递到catch
  • catch的参数一 与 then的参数二 , 二者只能使用其一







JavaScript Promise 和 then 方法详解

什么是 Promise?

Promise 是 JavaScript 中处理异步操作的核心机制,它代表一个异步操作的最终完成(或失败)及其结果值。Promise 提供了一种更优雅的方式来处理异步操作,避免了传统的回调地狱问题。

     Promise 的三种状态

  1. pending(等待中)(待定):初始状态 ; Pending(待定):初始状态,异步操作未完成。
  2. fulfilled(已成功)(已兑现):操作成功完成 ; Fulfilled(已兑现):异步操作成功完成,触发 resolve(value)
  3. rejected(已失败)(已拒绝):操作失败 ; Rejected(已拒绝):异步操作失败,触发 reject(reason)
  • 状态不可逆:一旦从 Pending 变为 Fulfilled 或 Rejected,状态不可更改。
pending
fulfilled
rejected

Promise 基本用法

     创建 Promise

const myPromise = new Promise((resolve, reject) => {
  // 异步操作
  setTimeout(() => {
    const success = Math.random() > 0.5;
    
    if (success) {
      resolve("操作成功!");
    } else {
      reject(new Error("操作失败"));
    }
  }, 1000);
});

     使用 Promise

myPromise
  .then(result => {
    console.log("成功:", result);
  })
  .catch(error => {
    console.error("失败:", error.message);
  })
  .finally(() => {
    console.log("操作完成(无论成功与否)");
  });

then 方法详解

then() 是 Promise 的核心方法,用于处理 Promise 的解决(fulfillment)或拒绝(rejection)。

     基本语法

promise.then(
  onFulfilled, // 成功时调用的函数
  onRejected   // 可选,失败时调用的函数
);

     then 方法的特性

         1. 链式调用

fetchData()
  .then(processData)
  .then(saveData)
  .then(result => {
    console.log("最终结果:", result);
  })
  .catch(error => {
    console.error("处理过程中出错:", error);
  });

         2. 返回值处理

const promise = new Promise(resolve => resolve(10));

promise
  .then(value => {
    console.log(value); // 10
    return value * 2;   // 返回新值
  })
  .then(value => {
    console.log(value); // 20
    return new Promise(resolve => setTimeout(() => resolve(value + 5), 1000));
  })
  .then(value => {
    console.log(value); // 25 (1秒后)
  });

         3. 错误处理

fetchData()
  .then(data => {
    if (!data.isValid) {
      throw new Error("无效数据");
    }
    return process(data);
  })
  .then(result => {
    console.log("处理结果:", result);
  })
  .catch(error => {
    console.error("发生错误:", error.message);
  });

Promise 链式调用的高级模式

     1. 值传递

getUser()
  .then(user => user.id)
  .then(userId => getOrders(userId))
  .then(orders => {
    console.log("用户订单:", orders);
  });

     2. 嵌套解构

getUser()
  .then(user => {
    return getProfile(user.id).then(profile => {
      return { user, profile };
    });
  })
  .then(({ user, profile }) => {
    console.log("用户数据:", user);
    console.log("个人资料:", profile);
  });

     3. 并行处理

Promise.all([
  getUser(),
  getProducts(),
  getCart()
])
  .then(([user, products, cart]) => {
    console.log("用户:", user);
    console.log("产品:", products);
    console.log("购物车:", cart);
  });

     4. 错误恢复

fetchPrimaryData()
  .catch(() => {
    console.log("主数据源失败,尝试备用数据源");
    return fetchBackupData();
  })
  .then(data => {
    console.log("最终数据:", data);
  });

then 方法的返回值

then() 方法总是返回一个新的 Promise,其状态由回调函数的执行结果决定:

回调函数返回值新 Promise 状态
返回值(非 Promise)fulfilled(值作为结果)
返回 Promise采用该 Promise 的状态
抛出错误rejected(错误作为原因)
无返回值fulfilled(undefined 作为结果)
const promise = new Promise(resolve => resolve(10));

const newPromise = promise.then(value => value * 2);

newPromise.then(result => console.log(result)); // 20

实际应用场景

     1. API 请求处理

function getUserData(userId) {
  return fetch(`/api/users/${userId}`)
    .then(response => {
      if (!response.ok) {
        throw new Error(`HTTP错误! 状态: ${response.status}`);
      }
      return response.json();
    })
    .then(user => {
      return fetch(`/api/users/${userId}/orders`);
    })
    .then(response => response.json())
    .then(orders => {
      return { user, orders };
    });
}

getUserData(123)
  .then(data => console.log("用户数据:", data))
  .catch(error => console.error("获取数据失败:", error));

     2. 顺序执行异步操作

function executeSequentially(promises) {
  return promises.reduce((chain, currentPromise) => {
    return chain.then(() => currentPromise);
  }, Promise.resolve());
}

const tasks = [
  () => delay(1000).then(() => console.log("任务1完成")),
  () => delay(500).then(() => console.log("任务2完成")),
  () => delay(1500).then(() => console.log("任务3完成"))
];

executeSequentially(tasks);

     3. 超时控制

function withTimeout(promise, timeout) {
  return new Promise((resolve, reject) => {
    const timer = setTimeout(() => {
      reject(new Error("操作超时"));
    }, timeout);
    
    promise
      .then(resolve)
      .catch(reject)
      .finally(() => clearTimeout(timer));
  });
}

const fetchWithTimeout = withTimeout(fetch('https://api.example.com/data'), 5000);

fetchWithTimeout
  .then(response => console.log("数据获取成功"))
  .catch(error => console.error("错误:", error.message));

Promise 静态方法

     1. Promise.resolve()

// 创建已解决的 Promise
const resolvedPromise = Promise.resolve("成功值");

// 等同于
new Promise(resolve => resolve("成功值"));

     2. Promise.reject()

// 创建已拒绝的 Promise
const rejectedPromise = Promise.reject(new Error("失败原因"));

// 等同于
new Promise((_, reject) => reject(new Error("失败原因")));

     3. Promise.all()

Promise.all([
  fetch('/api/user'),
  fetch('/api/posts'),
  fetch('/api/comments')
])
  .then(([user, posts, comments]) => {
    console.log("所有数据加载完成");
  })
  .catch(error => {
    console.error("至少一个请求失败:", error);
  });

     4. Promise.race()

Promise.race([
  fetch('/api/data'),
  new Promise((_, reject) => 
    setTimeout(() => reject(new Error("超时")), 5000)
  )
])
  .then(data => console.log("数据获取成功"))
  .catch(error => console.error("错误:", error.message));

     5. Promise.allSettled()

Promise.allSettled([
  Promise.resolve("成功"),
  Promise.reject("失败"),
  Promise.resolve("另一个成功")
])
  .then(results => {
    results.forEach((result, index) => {
      if (result.status === "fulfilled") {
        console.log(`Promise ${index}: 成功, 值: ${result.value}`);
      } else {
        console.log(`Promise ${index}: 失败, 原因: ${result.reason}`);
      }
    });
  });

错误处理最佳实践

     1. 使用 catch 处理错误

fetchData()
  .then(process)
  .catch(handleError); // 捕获前面所有步骤的错误

     2. 局部错误处理

fetchData()
  .then(data => {
    try {
      return process(data);
    } catch (error) {
      // 处理当前步骤错误
      return recoverFromError(error);
    }
  })
  .then(finalProcess)
  .catch(handleOtherErrors);

     3. 重新抛出错误

fetchData()
  .then(data => {
    if (!isValid(data)) {
      throw new ValidationError("无效数据");
    }
    return data;
  })
  .then(process)
  .catch(error => {
    if (error instanceof ValidationError) {
      console.warn("验证错误:", error.message);
      return getDefaultData();
    }
    throw error; // 重新抛出其他错误
  })
  .then(finalStep)
  .catch(handleUnexpectedError);

Promise 与 async/await

虽然 async/await 提供了更简洁的语法,但理解 Promise 和 then 方法仍然是基础:

// 使用 async/await
async function fetchData() {
  try {
    const response = await fetch('/api/data');
    const data = await response.json();
    return process(data);
  } catch (error) {
    handleError(error);
  }
}

// 等价于 then 版本
function fetchData() {
  return fetch('/api/data')
    .then(response => response.json())
    .then(process)
    .catch(handleError);
}

常见陷阱与解决方案

     1. 忘记返回 Promise

// 错误:没有返回 Promise
getUser()
  .then(user => {
    getOrders(user.id); // 没有返回
  })
  .then(orders => {
    // orders 是 undefined
  });

// 正确
getUser()
  .then(user => getOrders(user.id)) // 返回 Promise
  .then(orders => {
    // 处理订单
  });

     2. 错误处理位置不当

// 错误:catch 无法捕获回调中的错误
fetchData()
  .then(data => {
    setTimeout(() => {
      throw new Error("异步错误"); // 无法捕获
    }, 1000);
  })
  .catch(error => {
    // 不会执行
  });

// 正确:在 Promise 中封装异步操作
fetchData()
  .then(data => {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        try {
          resolve(process(data));
        } catch (error) {
          reject(error);
        }
      }, 1000);
    });
  })
  .catch(handleError);

     3. Promise 地狱

// 避免深层嵌套
getUser()
  .then(user => {
    return getProfile(user.id).then(profile => {
      return getOrders(user.id).then(orders => {
        return { user, profile, orders };
      });
    });
  });

// 改进:扁平化结构
getUser()
  .then(user => Promise.all([
    user,
    getProfile(user.id),
    getOrders(user.id)
  ]))
  .then(([user, profile, orders]) => {
    return { user, profile, orders };
  });

性能优化技巧

     1. 避免不必要的 then

// 不必要
fetchData()
  .then(data => data)
  .then(data => process(data));

// 直接
fetchData().then(process);

     2. 并行独立操作

// 顺序执行(慢)
getUser()
  .then(user => getOrders(user.id))
  .then(orders => getProducts(orders[0].id));

// 并行执行(快)
Promise.all([
  getUser(),
  getProducts()
]).then(([user, products]) => {
  // 同时处理结果
});

     3. 重用 Promise 实例

let userPromise;

function getUser() {
  if (!userPromise) {
    userPromise = fetch('/api/user');
  }
  return userPromise;
}

总结

Promise 和 then 方法是 JavaScript 异步编程的基石:

  1. Promise 状态:pending, fulfilled, rejected
  2. then 方法:处理成功和失败情况,返回新 Promise
  3. 链式调用:通过返回新值或 Promise 实现流程控制
  4. 错误处理:使用 catch 捕获链中任何位置的错误
  5. 静态方法:Promise.all, Promise.race 等提供高级控制

掌握 Promise 和 then 方法对于编写健壮、可维护的异步 JavaScript 代码至关重要。虽然 async/await 提供了更简洁的语法,但理解 Promise 的工作原理仍然是每个 JavaScript 开发者的必备技能。

















1️⃣ 参考 1

JavaScript Promise 和 then 方法详解

Promise 是 JavaScript 中处理异步操作的核心机制,它提供了一种更优雅、更强大的方式来处理异步编程。下面我将全面解析 Promise 及其 then 方法。

Promise 的基本概念

Promise 是一个表示异步操作最终完成或失败的对象,具有三种状态:

  • Pending(等待中):初始状态,操作尚未完成
  • Fulfilled(已成功):操作成功完成
  • Rejected(已失败):操作失败
resolve(value)
reject(reason)
Pending
Fulfilled
Rejected

创建 Promise

使用 new Promise() 构造函数创建 Promise 对象:

const myPromise = new Promise((resolve, reject) => {
  // 异步操作(如 API 请求、文件读取等)
  const success = true; // 模拟操作是否成功
  
  setTimeout(() => {
    if (success) {
      resolve('操作成功!'); // 状态变为 Fulfilled
    } else {
      reject('操作失败!'); // 状态变为 Rejected
    }
  }, 1000);
});

then 方法详解

then() 方法是 Promise 的核心,用于处理异步操作的结果:

     基本语法

promise.then(
  onFulfilled, // 成功时调用的函数
  onRejected   // 失败时调用的函数(可选)
);

     处理成功状态

myPromise.then(result => {
  console.log(result); // 输出:"操作成功!"
});

     处理失败状态

myPromise.then(
  result => console.log(result),
  error => console.error(error) // 输出:"操作失败!"
);

Promise 链式调用

then() 方法返回一个新的 Promise,因此可以链式调用:

fetchUserData()
  .then(user => {
    console.log('获取用户数据:', user);
    return fetchUserPosts(user.id); // 返回新 Promise
  })
  .then(posts => {
    console.log('获取用户帖子:', posts);
    return processPosts(posts); // 返回处理后的数据
  })
  .then(processedData => {
    console.log('处理后的数据:', processedData);
  })
  .catch(error => {
    console.error('处理过程中出错:', error);
  });

错误处理

     1. 使用 catch 方法

myPromise
  .then(result => {
    // 处理成功
  })
  .catch(error => {
    // 处理所有错误(包括 then 中的错误)
    console.error('捕获到错误:', error);
  });

     2. 使用 finally 方法

myPromise
  .then(result => { /*...*/ })
  .catch(error => { /*...*/ })
  .finally(() => {
    // 无论成功或失败都会执行
    console.log('操作完成');
  });

Promise 静态方法

     Promise.resolve()
创建一个已解决的 Promise:

const resolvedPromise = Promise.resolve('立即解决的值');

     Promise.reject()
创建一个已拒绝的 Promise:

const rejectedPromise = Promise.reject('错误原因');

     Promise.all()
并行处理多个 Promise,全部成功时返回结果数组:

Promise.all([promise1, promise2, promise3])
  .then(results => {
    console.log('所有操作完成:', results);
  })
  .catch(error => {
    console.error('至少一个操作失败:', error);
  });

     Promise.race()
返回第一个完成的 Promise(无论成功或失败):

Promise.race([promise1, promise2])
  .then(firstResult => {
    console.log('第一个完成的结果:', firstResult);
  });

实际应用示例

// 模拟 API 请求函数
function fetchData(url) {
  return new Promise((resolve, reject) => {
    console.log(`请求: ${url}`);
    setTimeout(() => {
      if (Math.random() > 0.3) { // 70% 成功率
        resolve(`${url} 的数据`);
      } else {
        reject(`${url} 请求失败`);
      }
    }, Math.random() * 2000);
  });
}

// 链式调用示例
fetchData('/api/users')
  .then(users => {
    console.log('用户数据:', users);
    return fetchData('/api/posts');
  })
  .then(posts => {
    console.log('帖子数据:', posts);
    return fetchData('/api/comments');
  })
  .then(comments => {
    console.log('评论数据:', comments);
    console.log('所有数据获取完成!');
  })
  .catch(error => {
    console.error('数据获取失败:', error);
  })
  .finally(() => {
    console.log('请求过程结束');
  });

// 并行请求示例
Promise.all([
  fetchData('/api/settings'),
  fetchData('/api/preferences'),
  fetchData('/api/config')
])
  .then(([settings, preferences, config]) => {
    console.log('所有配置数据:', {settings, preferences, config});
  });

Promise 最佳实践

  1. 始终返回结果:在 then 处理程序中返回一个值或 Promise
  2. 避免嵌套:使用链式调用而非嵌套 Promise
  3. 统一错误处理:在链的末尾使用 catch 捕获所有错误
  4. 命名 Promise 函数:提高代码可读性
  5. 考虑 finally:用于清理操作(如隐藏加载动画)

常见误区

// 错误:忘记返回 Promise
fetchData('/api/users')
  .then(users => {
    fetchData('/api/posts'); // 忘记 return!
  })
  .then(posts => {
    // posts 会是 undefined
  });

// 正确:返回 Promise
fetchData('/api/users')
  .then(users => {
    return fetchData('/api/posts');
  })
  .then(posts => {
    // 正确获取 posts
  });

Promise 是现代 JavaScript 异步编程的基石,理解 Promise 和 then 方法对于编写健壮、可维护的异步代码至关重要。

















2️⃣ 参考 2

JavaScript Promise 与 .then() 详解

     1. Promise 核心概念
Promise 是一个异步操作的容器,表示一个最终完成(或失败) 的操作及其结果值。

三种状态

  • pending(进行中):初始状态
  • fulfilled(已成功):操作成功完成
  • rejected(已失败):操作失败

状态转换不可逆:pendingfulfilledpendingrejected

     2. 创建 Promise

const promise = new Promise((resolve, reject) => {
  // 异步操作(如 API 请求、定时器等)
  if (/* 成功条件 */) {
    resolve(value); // 状态变为 fulfilled
  } else {
    reject(error);  // 状态变为 rejected
  }
});

示例

const fetchData = new Promise((resolve, reject) => {
  setTimeout(() => {
    const success = Math.random() > 0.5;
    success ? resolve("数据加载成功!") : reject("加载失败");
  }, 1000);
});

     3. ** .then() 方法详解**
.then() 用于处理 Promise 的完成状态(fulfilled)和拒绝状态(rejected)。

基本语法

promise.then(
  onFulfilled, // 成功回调函数 (value) => { ... }
  onRejected   // 可选失败回调函数 (error) => { ... }
);

特性

  1. 返回新的 Promise 对象,支持链式调用
  2. 回调函数返回值会被自动包装成 Promise
  3. 错误会沿链传递直到被捕获

     4. 链式调用实践

fetchData
  .then(
    result => {
      console.log("成功:", result);
      return "下一步处理"; // 返回值包装为 Promise.resolve("下一步处理")
    },
    error => {
      console.warn("初级错误处理:", error);
      throw new Error("处理失败"); // 抛出错误会被后续 catch 捕获
    }
  )
  .then(newResult => {
    console.log("第二阶段:", newResult); // "下一步处理"
  })
  .catch(err => {
    console.error("全局捕获:", err); // 捕获所有未处理的错误
  });

     5. 执行规则解析

场景返回值下一级 then 接收值
回调返回普通值Promise.resolve(值)该值
回调返回 Promise原样返回该 Promise该 Promise 的解决值
回调抛出错误Promise.reject(错误)catch 捕获该错误
未提供 onRejected 处理函数返回拒绝状态的 Promise错误传递到后续 catch

     6. 错误处理对比

// 方式 1:then 的第二个参数(仅捕获当前 Promise 错误)
promise.then(
  success => console.log(success),
  error => console.log("当前错误:", error) // 不捕获后续 then 的错
);

// 方式 2:catch(捕获链上所有未处理的错误)
promise
  .then(success => console.log(success))
  .catch(error => console.log("全局错误:", error));

     7. 高级链式操作

// 嵌套解构
getUser()
  .then(user => getPosts(user.id))
  .then(posts => getComments(posts[0].id))

// 值传递优化
getUser()
  .then(user => {
    return getPosts(user.id).then(posts => ({ user, posts }));
  })
  .then(({ user, posts }) => {
    console.log(user.name, "的文章数:", posts.length);
  });

     8. 与微任务队列的关系

console.log("开始");

Promise.resolve()
  .then(() => console.log("微任务 1"))
  .then(() => console.log("微任务 2"));

setTimeout(() => console.log("宏任务"), 0);

console.log("结束");

/* 输出顺序:
   开始
   结束
   微任务 1
   微任务 2
   宏任务
*/
  • Promise 回调属于微任务,优先于 setTimeout 等宏任务执行
  • 每次事件循环先清空微任务队列,再执行宏任务

     9. 静态方法速查

方法描述
Promise.resolve(value)创建已解决的 Promise
Promise.reject(error)创建已拒绝的 Promise
Promise.all([p1, p2])所有 Promise 成功时返回结果数组,任一失败立即拒绝
Promise.race([p1, p2])返回第一个完成的 Promise(无论成功/失败)
Promise.allSettled([p1, p2])所有 Promise 完成后返回结果对象数组(含状态和值)

     10. 经典应用场景
顺序异步操作

function asyncSequence() {
  return operation1()
    .then(result1 => operation2(result1))
    .then(result2 => operation3(result2))
    .catch(handleError);
}

并行异步操作

Promise.all([fetchData1(), fetchData2()])
  .then(([data1, data2]) => {
    console.log("全部数据:", data1, data2);
  })
  .catch(err => {
    console.log("至少一个请求失败", err);
  });

超时控制

function withTimeout(promise, timeout) {
  return Promise.race([
    promise,
    new Promise((_, reject) => 
      setTimeout(() => reject(new Error("超时")), timeout)
    )
  ]);
}

核心总结

  1. Promise 本质:异步操作的状态容器(pending/fulfilled/rejected)
  2. .then() 核心
    • 接收两个可选回调(成功/失败)
    • 返回新 Promise 实现链式调用
    • 自动处理返回值包装和错误传递
  3. 最佳实践
    • 使用 catch 统一处理错误
    • 避免嵌套 then,保持链式扁平化
    • 合理使用 Promise.all/Promise.race 优化流程

通过 Promise 和 .then() 的链式调用,可有效解决 “回调地狱” 问题,使异步代码具有同步代码的可读性。

















3️⃣ 参考 3

JavaScript Promise 和 then 方法详解

什么是 Promise?

Promise 是 JavaScript 中处理异步操作的核心对象,它表示一个异步操作的最终完成(或失败)及其结果值。

// 创建一个新的 Promise
const myPromise = new Promise((resolve, reject) => {
  // 异步操作(例如:API 调用、文件读取、定时器等)
  const operationSucceeded = true;
  
  if (operationSucceeded) {
    resolve("操作成功!"); // 状态变为 fulfilled
  } else {
    reject("操作失败!"); // 状态变为 rejected
  }
});

Promise 的三种状态

  1. Pending(待定):初始状态,既没有被兑现,也没有被拒绝
  2. Fulfilled(已兑现):操作成功完成
  3. Rejected(已拒绝):操作失败

then 方法详解

then() 方法是 Promise 的核心方法,用于处理 Promise 的最终状态(成功或失败)。

     基本语法

promise.then(
  onFulfilled,  // 当 Promise 被兑现时调用的函数
  onRejected    // 当 Promise 被拒绝时调用的函数(可选)
);

     处理成功状态

myPromise.then(
  (result) => {
    console.log("成功:", result); // 输出: 成功: 操作成功!
  }
);

     处理失败状态

myPromise.then(
  (result) => {
    console.log("成功:", result);
  },
  (error) => {
    console.log("失败:", error); // 当 Promise 被拒绝时执行
  }
);

Promise 链式调用

Promise 的强大之处在于链式调用能力,允许顺序执行多个异步操作。

fetchUserData(userId)
  .then((userData) => {
    console.log("用户数据:", userData);
    return fetchUserPosts(userData.id); // 返回新的 Promise
  })
  .then((posts) => {
    console.log("用户帖子:", posts);
    return fetchPostComments(posts[0].id); // 返回另一个 Promise
  })
  .then((comments) => {
    console.log("帖子评论:", comments);
  })
  .catch((error) => {
    console.error("处理过程中出错:", error);
  });

值传递与 Promise 传递

     返回普通值

Promise.resolve(10)
  .then((value) => {
    console.log(value); // 10
    return value * 2;   // 返回普通值
  })
  .then((value) => {
    console.log(value); // 20
  });

     返回 Promise

Promise.resolve(10)
  .then((value) => {
    console.log(value); // 10
    return new Promise(resolve => {
      setTimeout(() => resolve(value * 3), 1000);
    });
  })
  .then((value) => {
    console.log(value); // 30 (1秒后)
  });

错误处理

     使用 catch 方法

catch() 是专门用于处理错误的方法。

someAsyncOperation()
  .then((result) => {
    // 处理成功结果
  })
  .catch((error) => {
    // 处理所有错误
    console.error("发生错误:", error);
  });

     错误传播

在 Promise 链中,错误会一直向下传播,直到被捕获。

Promise.resolve()
  .then(() => {
    throw new Error("第一步出错!");
  })
  .then(() => {
    console.log("这一步不会执行");
  })
  .catch((error) => {
    console.error("捕获到错误:", error.message); // 捕获到错误: 第一步出错!
  });

Promise 静态方法

     Promise.resolve()

创建一个已解决的 Promise。

const resolvedPromise = Promise.resolve("立即解决的值");
resolvedPromise.then(value => console.log(value)); // 输出: 立即解决的值

     Promise.reject()

创建一个已拒绝的 Promise。

const rejectedPromise = Promise.reject("立即拒绝的原因");
rejectedPromise.catch(reason => console.log(reason)); // 输出: 立即拒绝的原因

     Promise.all()

等待所有 Promise 完成,或任何一个 Promise 失败。

const promise1 = Promise.resolve(1);
const promise2 = Promise.resolve(2);
const promise3 = new Promise(resolve => setTimeout(resolve, 100, 3));

Promise.all([promise1, promise2, promise3])
  .then(values => {
    console.log(values); // [1, 2, 3] (大约100ms后)
  });

     Promise.race()

返回第一个完成(解决或拒绝)的 Promise。

const promise1 = new Promise(resolve => setTimeout(resolve, 500, "慢的"));
const promise2 = new Promise(resolve => setTimeout(resolve, 100, "快的"));

Promise.race([promise1, promise2])
  .then(value => {
    console.log(value); // "快的" (大约100ms后)
  });

实际应用示例

     模拟 API 请求

function simulateAPI(endpoint, delay = 1000, success = true) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (success) {
        resolve(`${endpoint} 获取的数据 (${delay}ms)`);
      } else {
        reject(`请求 ${endpoint} 失败`);
      }
    }, delay);
  });
}

// 顺序执行多个 API 请求
simulateAPI("/users")
  .then(users => {
    console.log(users);
    return simulateAPI("/posts");
  })
  .then(posts => {
    console.log(posts);
    return simulateAPI("/comments");
  })
  .then(comments => {
    console.log(comments);
  })
  .catch(error => {
    console.error("API 请求失败:", error);
  });

// 并行执行多个 API 请求
Promise.all([
  simulateAPI("/users", 800),
  simulateAPI("/posts", 600),
  simulateAPI("/comments", 400)
])
.then(results => {
  console.log("所有数据获取完成:", results);
})
.catch(error => {
  console.error("并行请求出错:", error);
});

最佳实践

  1. 总是返回 Promise:在 then 回调中总是返回一个值或 Promise
  2. 避免嵌套:使用链式调用而不是嵌套的 then
  3. 使用 catch:在链的末尾添加 catch 处理所有错误
  4. 命名 Promise:为重要的 Promise 变量命名以提高可读性
  5. 处理错误:不要忽略 Promise 的拒绝状态
// 良好实践示例
getUserData()
  .then(validateUserData)
  .then(updateUserProfile)
  .then(sendConfirmationEmail)
  .then(() => {
    console.log("所有操作成功完成");
  })
  .catch(handleAllErrors);

Promise 和 then 方法为 JavaScript 异步编程提供了强大而优雅的解决方案,通过理解其核心概念和掌握链式调用,可以显著提高异步代码的可读性和可维护性。

















4️⃣ 参考 4

以下是关于 JavaScript 中 Promisethen 方法的详细解析,采用渐进式说明和代码示例:


一、Promise 的核心作用
解决的问题
传统回调函数(Callback)在处理多个异步操作时会导致“回调地狱”(Callback Hell),代码可读性和维护性差。Promise 通过链式调用(Chaining)解决了这一问题。

// 回调地狱示例
getData(a, (resultA) => {
  getData(resultA, (resultB) => {
    getData(resultB, (resultC) => {
      // ...更多嵌套
    });
  });
});

// Promise 链式调用
getData(a)
  .then(resultA => getData(resultA))
  .then(resultB => getData(resultB))
  .then(resultC => { /* 处理结果 */ });

二、Promise 的三个状态

  • Pending:初始状态,未完成或未拒绝。
  • Fulfilled:操作成功完成,通过 resolve() 触发。
  • Rejected:操作失败,通过 reject() 触发。
const promise = new Promise((resolve, reject) => {
  // 异步操作(如 API 请求)
  setTimeout(() => {
    if (success) {
      resolve("Success!"); // 状态变为 Fulfilled
    } else {
      reject("Error!");    // 状态变为 Rejected
    }
  }, 1000);
});

三、 then() 方法详解
     1. 基本语法

promise.then(
  onFulfilled, // 成功回调(可选)
  onRejected   // 失败回调(可选)
);

     2. 链式调用规则

  • 返回值传递:每个 then() 的返回值会作为下一个 then() 的输入。
  • 自动包装 Promise:如果回调返回非 Promise 值,会自动包装为 Promise.resolve(value)
  • 错误冒泡:若某个 then() 中发生错误,会跳过后续的 onFulfilled,直接触发最近的 onRejectedcatch()
// 示例:链式调用与错误冒泡
new Promise((resolve) => resolve(1))
  .then(result => {
    console.log(result); // 1
    return result + 1;   // 返回 2
  })
  .then(result => {
    console.log(result); // 2
    throw new Error("Oops!"); // 触发错误
  })
  .catch(error => {
    console.error(error); // 捕获错误
    return "Recovered";   // 恢复链式调用
  })
  .then(result => {
    console.log(result); // "Recovered"
  });

四、 then() vs catch() vs finally()

方法触发条件返回值处理
then(onFulfilled, onRejected)成功或失败返回新 Promise
catch(onRejected)仅失败(等价于 then(null, onRejected)返回新 Promise
finally()无论成功或失败不改变原 Promise 的值
// finally() 示例
fetch(url)
  .then(data => process(data))
  .catch(error => handleError(error))
  .finally(() => {
    // 无论成功失败都会执行(如关闭加载动画)
  });

五、Promise 静态方法

  1. Promise.all(iterable)
    所有 Promise 成功时返回结果数组,任一失败则立即拒绝。

    Promise.all([fetchA(), fetchB()])
      .then(([resultA, resultB]) => { /* 处理结果 */ });
    
  2. Promise.race(iterable)
    取第一个完成的 Promise(无论成功或失败)。

    Promise.race([fetchWithTimeout(), timeoutPromise])
      .then(handleSuccess)
      .catch(handleTimeout);
    
  3. Promise.allSettled(iterable)
    等待所有 Promise 完成,返回状态和结果数组。


六、常见误区与最佳实践

  1. 避免嵌套 Promise

    // 错误示例(冗余嵌套)
    promise.then(result => {
      promise2.then(result2 => { ... });
    });
    
    // 正确写法(链式调用)
    promise
      .then(result => promise2)
      .then(result2 => { ... });
    
  2. 始终返回或终止链式调用
    then() 中忘记返回会导致后续 then() 接收到 undefined

  3. 使用 async/await 简化代码

    async function fetchData() {
      try {
        const resultA = await fetchA();
        const resultB = await fetchB(resultA);
        return resultB;
      } catch (error) {
        handleError(error);
      }
    }
    

七、完整示例

// 模拟异步请求
function mockRequest(data, delay, shouldFail = false) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      shouldFail ? reject(`Error: ${data}`) : resolve(`Success: ${data}`);
    }, delay);
  });
}

// 链式调用 + 错误处理
mockRequest("Step 1", 1000)
  .then(result => {
    console.log(result); // "Success: Step 1"
    return mockRequest("Step 2", 1500, true); // 触发失败
  })
  .then(result => {
    console.log(result); // 不会执行
  })
  .catch(error => {
    console.error(error); // "Error: Step 2"
    return "Fallback Data"; // 恢复链式调用
  })
  .then(finalResult => {
    console.log("Final:", finalResult); // "Final: Fallback Data"
  });

通过以上内容,可以系统地理解 Promisethen() 的工作机制,并避免常见错误。如果需要进一步探讨具体场景或问题,请随时提问!

















5️⃣ 参考 5

以下是关于 JavaScript 中 Promise.then() 的详细解析,结合知识库内容和代码示例,帮助你全面理解其核心概念和使用方式。


1. Promise 的定义与状态
Promise 是 JavaScript 中处理异步操作的核心对象,它表示一个 尚未完成但最终会完成的操作 的结果。Promise 有三种状态:

  • Pending(进行中):初始状态,操作未完成。
  • Fulfilled(已成功):操作成功,返回结果。
  • Rejected(已失败):操作失败,抛出错误。

     1.1 创建 Promise
通过 new Promise(executor) 创建,executor 是一个包含异步逻辑的函数,接收 resolvereject 两个参数:

const myPromise = new Promise((resolve, reject) => {
  // 异步操作
  if (/* 成功条件 */) {
    resolve("成功结果"); // 转为 fulfilled 状态
  } else {
    reject("错误原因"); // 转为 rejected 状态
  }
});

     1.2 状态不可逆
一旦 Promise 的状态从 pending 变为 fulfilledrejected,状态将不可逆。例如:

const p = new Promise((resolve, reject) => {
  resolve("成功");
  reject("失败"); // 无效,状态已锁定为 fulfilled
});

2. .then() 方法详解
.then() 是 Promise 的核心方法,用于处理异步操作的结果。它接受两个可选参数:

  • onFulfilled:当 Promise 状态变为 fulfilled 时调用。
  • onRejected:当 Promise 状态变为 rejected 时调用。

     2.1 基本语法

promise.then(
  (result) => { /* 成功处理 */ },
  (error) => { /* 失败处理 */ }
);

     2.2 返回新 Promise
.then() 总是返回一个新的 Promise,支持链式调用。例如:

new Promise(resolve => resolve(10))
  .then(value => {
    console.log(value); // 输出 10
    return value * 2;
  })
  .then(result => {
    console.log(result); // 输出 20
  });

     2.3 错误处理
.then() 的第二个参数可以处理错误,但推荐使用 .catch()

new Promise((resolve, reject) => reject("错误"))
  .then(
    (value) => console.log("成功:", value),
    (error) => console.error("失败:", error) // 输出 "失败: 错误"
  );

3. 链式调用与中间值传递
链式调用是 Promise 的核心特性,每个 .then() 的返回值会传递给下一个 .then()

     3.1 示例:串联异步操作

function asyncAdd(a, b) {
  return new Promise(resolve => {
    setTimeout(() => resolve(a + b), 1000);
  });
}

asyncAdd(2, 3)
  .then(sum => asyncAdd(sum, 5)) // 返回新的 Promise
  .then(final => console.log(final)); // 输出 10(2秒后)

     3.2 返回值的类型影响

  • 返回普通值:下一个 .then() 接收到该值。
  • 返回 Promise:下一个 .then() 会等待该 Promise 完成后再执行。
  • 抛出错误:链式调用跳转到最近的 .catch()

4. 错误处理与恢复
     4.1 使用 .catch() 捕获错误

new Promise((resolve, reject) => reject("网络错误!"))
  .then(data => console.log("成功:", data))
  .catch(error => {
    console.error("错误:", error); // 输出 "错误: 网络错误!"
    return "默认数据"; // 恢复链式调用
  })
  .then(data => console.log("恢复后的数据:", data)); // 输出 "恢复后的数据: 默认数据"

     4.2 错误冒泡机制
未在 .then() 中处理的错误会沿链式调用传递到 .catch()

new Promise((resolve, reject) => reject("错误"))
  .then(value => {
    console.log(value); // 不会执行
  })
  .catch(error => {
    console.error("捕获错误:", error); // 输出 "捕获错误: 错误"
  });

5. 注意事项与常见问题
     5.1 避免链式调用断裂
如果 .then() 忘记返回值,后续的 .then() 将接收到 undefined

new Promise(resolve => resolve(10))
  .then(value => {
    console.log(value); // 输出 10
    // 忘记返回值
  })
  .then(value => {
    console.log(value); // 输出 undefined
  });

     5.2 并行执行多个异步操作
使用 Promise.all() 并行执行多个 Promise:

Promise.all([
  new Promise(resolve => setTimeout(() => resolve("结果1"), 1000)),
  new Promise(resolve => setTimeout(() => resolve("结果2"), 500)),
])
  .then(results => console.log("所有结果:", results)); // 输出 ["结果1", "结果2"]

     5.3 finally() 的作用
finally() 无论 Promise 成功或失败都会执行,常用于清理操作:

new Promise((resolve, reject) => resolve("操作完成"))
  .finally(() => console.log("清理资源")) // 无论成功/失败都会执行
  .then(result => console.log(result)); // 输出 "操作完成"

6. 示例代码汇总
     6.1 基本用法

const p = new Promise((resolve, reject) => {
  const success = Math.random() > 0.5;
  if (success) resolve("成功!");
  else reject("失败!");
});

p.then(
  result => console.log("成功:", result),
  error => console.error("失败:", error)
);

     6.2 链式调用与错误恢复

fetchData()
  .then(data => processData(data))
  .then(result => console.log("处理结果:", result))
  .catch(error => console.error("全局错误:", error));

7. 与 async/await 的对比

  • .then():适合链式调用,但嵌套较深时可读性较差。
  • async/await:语法更接近同步代码,推荐用于复杂异步流程。
// 使用 async/await
async function run() {
  try {
    const result = await new Promise(resolve => setTimeout(() => resolve("成功"), 1000));
    console.log(result);
  } catch (error) {
    console.error(error);
  }
}

总结

特性说明
Promise 状态pendingfulfilledrejected,状态不可逆
.then()处理成功或失败结果,返回新 Promise,支持链式调用
链式调用每个 .then() 的返回值传递给下一个 .then()
错误处理使用 .catch() 捕获错误,支持错误恢复
finally()无论成功/失败都会执行,用于清理资源

通过合理使用 Promise.then(),可以显著提升异步代码的可读性、可维护性,并避免“回调地狱”。

















6️⃣ 参考 6

JavaScript 中的 Promisethen 是异步编程的核心工具,它们解决了传统回调函数嵌套过深(“回调地狱”)的问题,让异步代码更具可读性和可维护性。下面详细解析:

一、Promise 核心概念
Promise 是一个对象,用于封装一个异步操作并表示其最终结果。它有三个互斥的状态:

  • pending(进行中):初始状态,异步操作未完成
  • fulfilled(已成功):异步操作完成,结果可用
  • rejected(已失败):异步操作出错,错误信息可用

状态一旦从 pending 变为 fulfilledrejected,就不可再改变(不可逆)。

     1. 创建创建 Promise
通过 new Promise() 构造函数创建,传入一个执行器函数(executor),该函数接收两个参数:

  • resolve(value):将状态从 pending 改为 fulfilled,并传递成功结果 value
  • reject(error):将状态从 pending 改为 rejected,并传递错误信息 error
// 示例:封装一个异步操作(如网络请求、定时器)
const promise = new Promise((resolve, reject) => {
  // 模拟异步操作(1秒后完成)
  setTimeout(() => {
    const success = Math.random() > 0.5; // 50%概率成功
    if (success) {
      resolve("操作成功,返回结果"); // 成功时调用resolve
    } else {
      reject(new Error("操作失败,出错了")); // 失败时调用reject
    }
  }, 1000);
});

二、then() 方法:处理异步结果
then() 是 Promise 实例的核心方法,用于注册异步操作完成后的回调函数,并返回一个新的 Promise 实例(这是链式调用的基础)。

     1. 基本语法

promise.then(
  onFulfilled,  // 可选:当状态为fulfilled时执行的回调
  onRejected    // 可选:当状态为rejected时执行的回调
);
  • onFulfilled(value):接收 resolve 传递的成功结果 value
  • onRejected(error):接收 reject 传递的错误信息 error

     2. 执行逻辑

  • 当 Promise 状态变为 fulfilled 时,调用 onFulfilled 并传入结果
  • 当 Promise 状态变为 rejected 时,调用 onRejected 并传入错误
  • 若 Promise 状态已确定(非 pending),则回调会立即执行
  • 若回调未提供(如只传了 onFulfilled),则结果/错误会"穿透"到下一个 then

     3. 关键特性:链式调用
then() 返回新的 Promise,因此可以连续调用 .then(),每个 then 的回调可以处理上一步的结果:

// 链式调用示例
new Promise((resolve) => {
  resolve(10); // 第一步返回10
})
.then((num) => {
  console.log("第一步结果:", num); // 输出10
  return num * 2; // 返回20,作为下一个then的输入
})
.then((num) => {
  console.log("第二步结果:", num); // 输出20
  return num + 5; // 返回25
})
.then((num) => {
  console.log("第三步结果:", num); // 输出25
});

     4. 错误处理
then() 的第二个参数 onRejected 可处理错误,但更推荐用 catch()then(null, onRejected) 的语法糖)统一捕获:

new Promise((resolve, reject) => {
  reject(new Error("原始错误"));
})
.then(
  (result) => { console.log("成功:", result); },
  (error) => { console.log("捕获错误:", error.message); } // 输出"原始错误"
);

// 更推荐的写法(用catch统一处理)
new Promise((resolve, reject) => {
  reject(new Error("原始错误"));
})
.then((result) => { console.log("成功:", result); })
.catch((error) => { console.log("捕获错误:", error.message); }); // 输出"原始错误"

     5. 返回值处理
then() 回调的返回值会决定新 Promise 的状态:

  • 若返回非 Promise 值(如数字、对象),新 Promise 状态为 fulfilled,并将该值作为结果
  • 若返回另一个 Promise,新 Promise 会"等待"该 Promise 完成,状态和结果与其一致
  • 若回调中抛出异常throw new Error(...)),新 Promise 状态为 rejected,错误为抛出的值
// 示例:返回Promise
new Promise((resolve) => resolve(1))
.then((num) => {
  return new Promise((resolve) => {
    setTimeout(() => resolve(num * 10), 500); // 500ms后返回10
  });
})
.then((num) => console.log(num)); // 输出10

三、实际应用场景

  1. 处理网络请求(如 fetch API 返回 Promise):

    fetch("https://api.example.com/data")
      .then((response) => response.json()) // 解析JSON
      .then((data) => console.log("获取数据:", data)) // 处理数据
      .catch((error) => console.log("请求失败:", error)); // 捕获错误
    
  2. 串联多个依赖的异步操作

    // 场景:先获取用户ID,再查用户详情,最后更新UI
    getUserId()
      .then((id) => getUserInfo(id)) // 依赖上一步的id
      .then((info) => updateUI(info)) // 依赖上一步的info
      .catch((error) => showError(error)); // 任何步骤出错都会被捕获
    

四、总结

  • Promise 用于封装异步操作,通过 resolve/reject 改变状态
  • then() 用于注册状态改变后的回调,返回新 Promise 支持链式调用
  • 链式调用解决了回调嵌套问题,让异步逻辑更清晰
  • 错误可以通过 then 的第二个参数或 catch 捕获,实现统一错误处理

掌握 Promisethen 是理解更高级异步语法(async/await)的基础,也是现代 JavaScript 开发的必备技能。

















7️⃣ 参考 7

下面把 Promise 本身.then() 方法 彻底拆成「一张纸」能说清的全部细节。
你可以把它当成速查手册,也可以按顺序读一遍就能 100 % 掌握。

────────────────
一、Promise 是什么?
────────────────

  1. 一个状态机,只有 3 个互斥状态
    • pending(进行中)
    • fulfilled(已成功)
    • rejected(已失败)

  2. 状态变迁规则
    • 只能从 pending → fulfilled
    • 或从 pending → rejected
    一旦落定,永不可再变

  3. 创建语法

const p = new Promise((resolve, reject) => {
  // 1) 这函数叫 executor,会**立即同步**执行
  // 2) 你负责在合适的时机调用 resolve(value) 或 reject(reason)
});

────────────────
二、.then() 是什么?
────────────────

  1. 定义
    挂在 Promise 原型上的方法:Promise.prototype.then(onFulfilled, onRejected)

  2. 作用
    • 在当前 Promise 落定后执行对应回调
    • 返回一个全新的 Promise,因此可链式调用

  3. 形参
    • onFulfilled(value) — 状态变为 fulfilled 时触发
    • onRejected(reason) — 状态变为 rejected 时触发

  4. 返回值规则(⭐面试常考)
    | 你在回调里 return … | .then 返回的新 Promise 会变成 |
    |------------------------------------|----------------------------------|
    | 非 thenable 的普通值 | fulfilled,携带该值 |
    | 一个新的 Promise | 以它的最终状态/值为准 |
    | 抛出异常 throw err | rejected,携带该异常 |

示例:

Promise.resolve(1)
  .then(x => x + 1)                // return 2
  .then(x => Promise.reject('Oops'))// 新 Promise rejected
  .catch(e => console.log(e));     // Oops

────────────────
三、执行时机 & 微任务队列
────────────────
.then() 注册的回调永远当前栈清空后微任务阶段执行。
这保证了顺序可预测。

console.log(1);
Promise.resolve().then(() => console.log(3));
console.log(2);
// 输出顺序:1 → 2 → 3

────────────────
四、空值 & 透传
────────────────
如果你给 .thennull/undefined 或者干脆不传,Promise 会把值向下透传

Promise.resolve('A')
  .then()          // 没有参数,相当于 .then(v => v)
  .then(console.log); // A

────────────────
五、错误处理路径
────────────────

  1. 显式返回 rejected Promise
.then(() => Promise.reject('fail'))
  1. 抛出异常
.then(() => { throw new Error('fail'); })
  1. 这两种写法在 .then 内部等价,都会使链进入下一个 onRejected.catch

────────────────
六、对比 .catch(onRejected)
────────────────
.then(null, onRejected).catch(onRejected) 差异:

.then(null, onRejected) 只捕获它前面那个 Promise 的 reject
.catch 会捕获链上任何位置抛出的错误(更常用)

────────────────
七、完整模板代码
────────────────

function delay(ms, fail = false) {
  return new Promise((resolve, reject) => {
    setTimeout(() => (fail ? reject('超时') : resolve(ms)), ms);
  });
}

delay(1000)
  .then(ms => {
    console.log(`${ms} ms`);
    return delay(500, true);           // 故意失败
  })
  .then(
    val => console.log('成功:', val), // 不执行
    err => console.log('捕获:', err)  // 捕获 500 ms 的失败
  );

────────────────
八、一句话总结
────────────────
Promise 是“状态容器”,.then() 是“状态落定后的回调注册器 + 新 Promise 工厂”。
记住「状态唯一、链式返回、微任务执行、返回值决定后续」这四条,就永远不会踩坑。

















8️⃣ 参考 8

JavaScript Promise .then() 方法详解
.then() 是 Promise 链式调用的核心方法,用于处理异步操作的成功或失败结果。以下是全面解析:


     一、基本语法与返回值

promise.then(onFulfilled, onRejected);
  • onFulfilled:Promise 状态变为 fulfilled 时触发的回调,接收成功值作为参数
  • onRejected:Promise 状态变为 rejected 时触发的回调,接收错误原因作为参数
  • 返回值必定返回一个新 Promise 对象(与原始 Promise 不同)
const p = new Promise(resolve => resolve(10));
const p2 = p.then(val => val * 2); 

console.log(p2 instanceof Promise); // true
console.log(p2 === p); // false 

     二、链式调用机制
每个 .then() 返回的新 Promise 状态由回调函数的返回值决定:

回调返回值类型新 Promise 状态行为
普通值(非 Promise)fulfilled值作为下一环输入
新 Promise 对象与该 Promise 一致等待其状态变化
抛出错误rejected触发链中最近的 .catch()

示例:链式传递值

new Promise(resolve => resolve(5))
  .then(x => x * 2)       // 返回 10 (fulfilled)
  .then(y => y + 3)       // 返回 13 (fulfilled)
  .then(console.log);     // 输出: 13

     三、错误处理流程

fetchData()
  .then(processData) 
  .then(saveData)
  .catch(error => {       // 捕获链中任意错误
    console.error("失败:", error);
    return fallbackData;  // 返回备用数据
  })
  .then(finalStep);       // 继续执行
  • 错误冒泡:链中任一环节抛出错误(或返回 rejected Promise),会跳过后续 .then(),直达最近的 .catch()
  • 隐式转换:同步错误会被自动转为 rejected Promise:
    .then(() => {
      throw new Error("Oops!"); // → rejected Promise
    })
    

     四、执行顺序与微任务

  • 微任务队列.then() 回调始终在同步代码执行后、宏任务(如 setTimeout)前执行
    console.log("Start");
    Promise.resolve().then(() => console.log("Microtask"));
    setTimeout(() => console.log("Macrotask"));
    console.log("End");
    
    // 输出顺序: 
    // Start → End → Microtask → Macrotask
    

     五、核心使用场景

  1. 顺序异步操作
    login(user)
      .then(getUserProfile)   // 依赖登录结果
      .then(renderUI);         // 依赖用户数据
    
  2. 错误恢复
    fetch("/api/data")
      .catch(() => ({ data: "Default" })) // 失败时返回默认值
      .then(display);          // 始终有数据输入
    
  3. 条件分支
    checkPermission()
      .then(hasAccess => 
        hasAccess ? loadContent() : showBlockedPage()
      )
    

     六、注意事项

  1. 回调非必传:省略回调时值会透传
    Promise.resolve(10)
      .then()                 // 透传 10
      .then(v => console.log(v)); // 输出: 10
    
  2. 返回值影响:未显式返回时下一环获 undefined
  3. 状态不可逆:Promise 状态一旦变为 fulfilled/rejected 便不可更改

相关问题

  1. 如何用 .then() 实现多个 Promise 并行执行并合并结果?
  2. .catch(error => {...}).then(null, error => {...}) 有何区别?
  3. 为什么说 Promise 能解决“回调地狱”?请举例说明。
  4. 如何中断一个 Promise 链的执行?
引用说明:
.then() 返回新 Promise 对象,支持链式调用。
Promise 状态不可逆且错误会冒泡。
.then() 内部创建新 Promise 实现状态传递。

















9️⃣ 参考 9

JavaScript 的 Promise 与 then 方法详解


     一、Promise 的核心机制

  1. 状态与生命周期
    Promise 有三种状态:

    • Pending(进行中):初始状态,既未成功也未失败。
    • Fulfilled(已成功):操作成功完成,调用 resolve
    • Rejected(已失败):操作失败,调用 reject
      状态一旦改变不可逆,例如从 pending 变为 fulfilled 后无法再变为 rejected
  2. 创建 Promise

    const promise = new Promise((resolve, reject) => {
      // 异步操作(如网络请求、定时器)
      if (success) resolve(value); // 成功时调用 resolve
      else reject(error);          // 失败时调用 reject
    });
    

     二、 then 方法的深度解析

  1. 基本语法与参数
    then 方法接收两个可选回调函数:

    • onFulfilled:处理成功状态(fulfilled),接收 resolve 的值。
    • onRejected:处理失败状态(rejected),接收 reject 的原因。
    promise.then(
      value => { /* 处理成功 */ },
      error => { /* 处理失败 */ }
    );
    
  2. 返回值与链式调用

    • then 返回一个新的 Promise,允许链式调用。
    • 返回普通值:新 Promise 以该值 fulfilled
    • 返回 Promise:新 Promise 的状态和值由返回的 Promise 决定。
    // 链式调用示例
    fetchData()
      .then(data => processData(data))
      .then(result => console.log(result));
    
  3. 错误处理

    • 错误冒泡:未捕获的错误会沿 Promise 链传递,直到被 .catch() 捕获。
    • 同步错误:在 onFulfilledonRejected 中抛出的错误会触发新 Promise 的 rejected
    promise
      .then(() => { throw new Error("出错"); })
      .catch(error => console.error(error));
    

     三、链式调用的执行逻辑

  1. 微任务队列调度

    • then 的回调函数会被放入 微任务队列(Microtask Queue),优先于宏任务(如 setTimeout)执行。
    • 示例:
      console.log("Start");
      Promise.resolve().then(() => console.log("Microtask"));
      setTimeout(() => console.log("Macrotask"), 0);
      // 输出顺序:Start → Microtask → Macrotask
      
  2. 链式调用的值传递

    • 每个 then 的返回值作为下一个 onFulfilled 的输入。
    • 返回 Promise:需等待其完成才能传递值。
    Promise.resolve(1)
      .then(v => v + 1)          // 返回普通值 2
      .then(v => new Promise(resolve => setTimeout(() => resolve(v * 2), 100))) // 返回 Promise
      .then(v => console.log(v)); // 200(延迟 100ms 后输出)
    

     四、实际应用场景

  1. 链式数据处理

    fetchUser()
      .then(user => fetchPosts(user.id)) // 根据用户 ID 获取帖子
      .then(posts => posts[0].comments)  // 提取第一条帖子的评论
      .then(comments => console.log(comments));
    
  2. 错误恢复

    fetch("https://api.example.com/data")
      .then(response => {
        if (!response.ok) throw new Error("请求失败");
        return response.json();
      })
      .catch(error => {
        console.error("捕获错误:", error);
        return { data: "默认值" }; // 返回新值恢复流程
      })
      .then(data => console.log(data));
    
  3. 并行任务组合

    Promise.all([fetchUser(), fetchSettings()])
      .then(([user, settings]) => {
        // 同时处理用户和配置数据
      });
    

     五、注意事项与最佳实践

  1. 避免未处理的 Promise

    • 未附加 .catch() 的 Promise 拒绝会导致全局错误(如 UnhandledPromiseRejectionWarning)。
  2. 返回值类型的影响

    • 返回 Promise.resolve()Promise.reject() 会改变链式调用的状态。
  3. 同步代码优先执行

    • Promise 构造函数内的代码是同步执行的,.then() 回调是异步的。
    new Promise(resolve => {
      console.log("同步代码");
      resolve();
    }).then(() => console.log("异步回调"));
    // 输出顺序:同步代码 → 异步回调
    

     六、底层原理与手写实现

  1. 状态机与回调队列

    • Promise 内部维护 state(状态)、value(结果/错误)和 callbacks(回调队列)。
    • 当状态变更时,依次执行队列中的回调函数。
  2. 极简版 Promise 实现

    class MyPromise {
      constructor(executor) {
        this.state = "pending";
        this.value = null;
        this.callbacks = [];
        
        const resolve = (value) => {
          if (this.state !== "pending") return;
          this.state = "fulfilled";
          this.value = value;
          this.callbacks.forEach(cb => cb.onFulfilled(value));
        };
        
        executor(resolve, (reason) => {
          if (this.state !== "pending") return;
          this.state = "rejected";
          this.value = reason;
          this.callbacks.forEach(cb => cb.onRejected(reason));
        });
      }
      
      then(onFulfilled, onRejected) {
        return new MyPromise((resolve, reject) => {
          if (this.state === "fulfilled") {
            try {
              resolve(onFulfilled(this.value));
            } catch (e) {
              reject(e);
            }
          } else if (this.state === "rejected") {
            try {
              resolve(onRejected(this.value));
            } catch (e) {
              reject(e);
            }
          } else {
            this.callbacks.push({
              onFulfilled: (v) => resolve(v),
              onRejected: (e) => reject(e)
            });
          }
        });
      }
    }
    

总结

  • Promise 的核心价值:解决回调地狱,提供清晰的异步流程控制。
  • then 方法的关键作用:通过链式调用和值传递,实现异步操作的顺序执行与错误处理。
  • 最佳实践:始终使用 .catch() 捕获错误,合理设计链式结构,避免过度嵌套。

通过掌握 Promise 和 then 的机制,可以显著提升 JavaScript 异步代码的可读性和可维护性。

















🔟 参考 10

以下是针对 JavaScript 中 Promise.then() 的超详细解析,涵盖核心机制、用法技巧及典型场景:


🔧 一、Promise 深度拆解
     ✅ 本质与设计目标

  • 核心定位Promise 是 ES6 引入的异步编程容器,用于解决传统回调函数导致的「回调地狱」(Nested Callbacks)问题。
  • 关键特性:将异步操作的结果封装为一个对象,通过状态机(Pending → Fulfilled/Rejected)管理执行流程。

     ⚙️ 生命周期三态

状态描述特点
pending初始状态,等待异步操作完成可转换为其他两种状态
fulfilled异步成功,携带结果值(value触发 .then() 回调
rejected异步失败,携带原因(reason)(通常是 Error 对象)触发 .catch() 或第二个 .then() 参数

     🏗️ 构造函数全貌

new Promise((resolve, reject) => {
    // ✅ 同步代码在此立即执行
    // 🌟 需在此函数内手动调用 resolve(value) 或 reject(reason)
});

         📌 关键规则:

  1. 同步启动:构造函数传入的执行器函数会立即同步执行
  2. 状态不可逆:一旦从 pending 转为 fulfilledrejected,状态永久锁定。
  3. 忽略后续调用:若已确定最终状态,再次调用 resolve/reject 会被忽略。

     🌰 基础示例

const p = new Promise((resolve, reject) => {
    setTimeout(() => { // 模拟异步操作
        const success = Math.random() > 0.5; // 随机决定成功/失败
        if (success) resolve("OK");          // 走向 fulfilled
        else reject(new Error("Fail"));      // 走向 rejected
    }, 1000);
});

p.then(val => console.log("Success:", val)) // 成功时触发
 .catch(err => console.error("Error:", err)); // 失败时触发

🔗 二、.then() 方法深度剖析
     💡 核心功能

  • 注册成功回调:当 Promise 变为 fulfilled 状态时,执行传入的回调函数。
  • 返回新 Promise:始终返回一个新的 Promise 对象,实现链式调用。

     📝 语法糖形式

promise.then(
    onFulfilled?,    // 成功回调(可选)
    onRejected?      // 失败回调(可选,等同于 .catch())
);

         ⚠️ 重要特性:

  1. 穿透值传递

    • onFulfilled 显式返回一个值,该值会成为新 Promise 的 value
    • 若未返回值,默认返回 undefined
    • 若抛出异常,新 Promise 将立即变为 rejected
  2. 错误冒泡机制

    promise
      .then(res => { throw new Error("Custom Error"); }) // 抛出错误
      .catch(err => console.log(err)); // 捕获上层错误
    
  3. 链式调用的本质

    Promise.resolve(1)
      .then(v => v * 2)       // 返回 2 → 新 Promise
      .then(v => v + 3)       // 返回 5 → 新 Promise
      .then(v => console.log(v)); // 输出 5
    

     📦 进阶用法
         ❶ 值转换技巧

输入值.then() 行为输出值
Promise.resolve(42)直接透传42
Promise.reject(err)跳转至下一个 .catch()undefined
null, undefined, false, 0, ""均被视为有效值传递同输入

         ❷ 多参回调的处理

  • 方案一:返回对象
    promise.then(({ data, status }) => { /* ... */ });
    
  • 方案二:使用展开运算符
    promise.then(([first, ...rest]) => { /* ... */ });
    

         ❸ 终止链式调用

  • 显式中断:返回 undefinednull
    promise.then(res => {
      if (!res) return; // 提前终止链式调用
      return processRes(res);
    });
    

🔥 三、实战场景对比表

场景传统回调写法Promise + .then() 写法优势体现
单次异步操作fs.readFile("file.txt", (err, data) => {...});readFile("file.txt").then(data => {...}).catch(err => {...});避免嵌套
连续依赖操作深层嵌套的匿名函数扁平化的链式调用可读性大幅提升
错误处理需要在每个层级判断 err统一的 .catch() 末尾处理集中化错误管理
并行请求手动计数器跟踪完成情况Promise.all([req1, req2]).then([...])简洁高效的并发控制

❗ 四、常见误区警示
     ❌ 误解一:.then() 只会执行一次

const p = Promise.resolve(1);
p.then(v => { console.log(v); return v + 1; }) // 日志1
p.then(v => { console.log(v); return v + 1; }); // 日志1(非预期)

👉 真相:同一个 Promise 可以多次调用 .then(),每次都会获得相同的初始值。如需持续观察变化,应使用 MutationObserver 或其他数据绑定方案。

     ❌ 误解二:忽略返回值类型

Promise.resolve({ a: 1 })
  .then(obj => obj.b) // undefined
  .then(v => console.log(v)); // 输出 undefined

👉 解决方案:确保链式调用中每个环节都正确处理返回值类型。

     ❌ 误解三:混淆异步顺序

console.log(1);
setTimeout(() => console.log(2));
Promise.resolve().then(() => console.log(3));
console.log(4);
// 实际输出:1 → 4 → 3 → 2

👉 原理Promise.then() 的回调属于微任务队列,会在同步任务(如 console.log(4))之后执行,但在宏任务(如 setTimeout)之前执行。


💎 五、最佳实践指南

  1. 单一职责原则:每个 .then() 只做一件事(数据处理/视图更新/API调用等)。
  2. 错误边界处理:始终在链式调用末尾添加 .catch(),防止未捕获异常导致进程退出。
  3. 避免内存泄漏:对于不再需要的 Promise,及时取消请求(如 AbortController)。
  4. 类型校验:在 .then() 回调中验证输入值的类型和结构。
  5. 性能优化:对于频繁触发的操作,使用防抖(debounce)或节流(throttle)技术。

📚 六、关联知识扩展

概念说明
Promise.all()等待所有 Promise 完成,任一失败即拒绝
Promise.race()竞争第一个完成的 Promise,快照决
Promise.allSettled()等待所有 Promise 结算(无论成功/失败),返回包含状态的对象数组
async/await基于 Promise 的语法糖,提供同步风格的异步代码书写体验

总结Promise.then() 是 JavaScript 异步编程的基石,通过合理使用它们可以显著提升代码的可维护性和可读性。关键在于理解其状态机模型、链式调用机制以及错误处理策略。

















🤔 参考 11

当然可以,下面是对 JavaScript 中 Promisethen 的详细讲解,适合初学者和需要巩固基础的同学。


一、Promise 是什么?

在 JavaScript 中,Promise 是一种用于处理异步操作的对象。它代表一个未来可能完成(或失败)的操作,并返回一个结果。

Promise 有三种状态:

状态含义说明
pending(进行中)初始状态,既未成功,也未失败Promise 刚创建时的状态
fulfilled(成功)操作成功完成调用 resolve() 后的状态
rejected(失败)操作失败调用 reject() 后的状态

     创建一个 Promise 的基本语法:

const myPromise = new Promise((resolve, reject) => {
  // 异步操作
  if (操作成功) {
    resolve("成功的结果");
  } else {
    reject("失败的原因");
  }
});

二、then 方法详解

.then() 是 Promise 的一个方法,用于指定 Promise 成功或失败后的处理函数。

     语法:

myPromise.then(onFulfilled, onRejected);
  • onFulfilled:当 Promise 成功(fulfilled)时调用的函数。
  • onRejected:当 Promise 失败(rejected)时调用的函数(可选)。

     示例:

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("操作成功");
    // reject("操作失败");
  }, 1000);
});

myPromise.then(
  (result) => {
    console.log("成功:", result); // 输出:成功: 操作成功
  },
  (error) => {
    console.log("失败:", error); // 如果 reject 被调用,会输出:失败: 操作失败
  }
);

三、then 的链式调用(Promise 链)

.then() 可以链式调用,前一个 .then() 的返回值会作为下一个 .then() 的参数。

     示例:

fetchData()
  .then((data1) => {
    console.log("第一步结果:", data1);
    return data1 + " 处理后";
  })
  .then((data2) => {
    console.log("第二步结果:", data2);
  })
  .catch((error) => {
    console.error("出错了:", error);
  });

function fetchData() {
  return new Promise((resolve) => {
    setTimeout(() => resolve("原始数据"), 1000);
  });
}

     输出:

第一步结果: 原始数据
第二步结果: 原始数据 处理后

四、错误处理:catch

建议使用 .catch() 来捕获 Promise 链中的错误。

myPromise
  .then((result) => {
    console.log("成功:", result);
  })
  .catch((error) => {
    console.error("出错啦:", error);
  });

五、then 方法的返回值

.then() 本身也会返回一个新的 Promise,这样可以实现链式调用。

.then() 返回值类型新 Promise 的状态
返回一个值(如字符串、数字等)fulfilled
返回一个 Promise 对象由该 Promise 决定
抛出异常(throw)rejected

六、总结

概念说明
Promise用于处理异步操作的对象,有三种状态:pending、fulfilled、rejected
resolve()将 Promise 状态变为 fulfilled,并传递结果
reject()将 Promise 状态变为 rejected,并传递错误
.then()处理成功或失败的结果,支持链式调用
.catch()捕获 Promise 链中的错误

掌握 Promise 和 then 是理解 JavaScript 异步编程的关键。它为处理回调地狱(callback hell)提供了更清晰的结构和更好的可读性。

















🤔 参考 12

以下是对 JavaScript 中 Promisethen() 方法的详解,结合核心机制、使用场景及注意事项,综合多篇权威资料整理而成:


⚙️ 一、Promise 的核心概念

  1. 三种状态

    • Pending(待定):初始状态,异步操作未完成。
    • Fulfilled(已兑现):异步操作成功完成,触发 resolve(value)
    • Rejected(已拒绝):异步操作失败,触发 reject(reason)
    • 状态不可逆:一旦从 Pending 变为 Fulfilled 或 Rejected,状态不可更改。
  2. 创建 Promise

    const promise = new Promise((resolve, reject) => {
      // 异步操作(如 API 请求、定时器)
      if (/* 成功 */) resolve(value); 
      else reject(new Error("失败原因"));
    });
    
    • 执行器函数((resolve, reject) => {}同步执行,内部异步操作完成后调用 resolve/reject

🔗 二、 then() 方法详解
     1. 基本语法

promise.then(
  onFulfilled?: (value) => TResult | Promise<TResult>,
  onRejected?: (reason) => TError | Promise<TError>
): Promise<TResult | TError>
  • onFulfilled:Promise 成功时调用,接收解决值(value)。
  • onRejected:Promise 失败时调用,接收拒绝原因(reason)。
  • 返回值总是返回一个新 Promise,其状态由回调函数的执行结果决定。

     2. 链式调用机制
then() 的链式调用是 Promise 的核心优势,解决了回调地狱问题:

fetchData()
  .then(processData)   // 步骤1:处理数据
  .then(saveData)       // 步骤2:保存数据
  .catch(handleError);  // 统一捕获错误
  • 每个 then() 返回新 Promise:后续 then() 处理前一个 then() 返回的结果。
  • 回调返回值决定新 Promise 状态
    • 返回普通值(如 42"ok"):新 Promise 立即进入 Fulfilled 状态,值为该返回值。
    • 返回新 Promise:新 Promise 跟随其状态(如返回 Promise.resolve() 则成功)。
    • 抛出错误:新 Promise 进入 Rejected 状态,错误被后续 catch() 捕获。

     3. 参数默认行为

  • 忽略 onFulfilled:成功值直接传递给下一个 then()(透传)。
  • 忽略 onRejected:错误继续向下传递,直到被 catch() 捕获。
    Promise.reject("Error")
      .then(null) // 忽略 onRejected,错误继续传递
      .catch(err => console.log(err)); // 捕获错误
    

⚠️ 三、关键注意事项

  1. 错误处理优先级

    • 使用 .catch()onRejected 捕获错误,避免未处理错误导致程序静默失败。
    • 链式调用中,一个 catch() 可捕获前面任意环节的错误
  2. 微任务队列(Microtask Queue)

    • then() 的回调在微任务队列执行,优先于宏任务(如 setTimeout):
      setTimeout(() => console.log("Macro"), 0);
      Promise.resolve().then(() => console.log("Micro"));
      // 输出顺序: "Micro" → "Macro"
      
  3. 同步错误自动转拒绝

    • then() 回调中抛出同步错误(如 throw new Error()),会自动触发新 Promise 的拒绝:
      Promise.resolve()
        .then(() => { throw "Oops!" })
        .catch(err => console.log(err)); // 捕获 "Oops!"
      

💡 四、典型应用场景

  1. 链式异步操作

    fetchUser() // 返回 Promise
      .then(user => fetchOrder(user.id)) // 返回新 Promise
      .then(order => processPayment(order))
      .then(payment => console.log(payment));
    
  2. 错误恢复

    fetchData()
      .catch(err => { // 捕获错误
        console.log("使用缓存数据");
        return getCachedData(); // 返回新值继续链式调用
      })
      .then(data => render(data));
    
  3. 并行操作(Promise.all

    Promise.all([fetchUser(), fetchOrders()])
      .then(([user, orders]) => mergeData(user, orders));
    

五、常见误区与解决

问题现象原因解决方案
Promise 永久 Pending未调用 resolve/reject检查异步操作是否触发状态变更
链式调用中断某环节未返回有效值确保回调函数有返回值
错误未被捕获遗漏 .catch()链式末尾添加 .catch()

💎 总结

  • then() 是 Promise 链式调用的核心:通过返回新 Promise 实现异步流程控制。
  • 返回值决定链式状态:普通值 ⇒ 成功,Promise ⇒ 跟随状态,错误 ⇒ 拒绝。
  • 错误处理是重点:始终用 .catch()onRejected 兜底,避免静默失败。
  • 微任务机制影响执行顺序then() 回调优先于宏任务执行。

示例代码参考自 ,概念解析综合 。

















🤔 参考 13

JavaScript Promise 与 then 方法详解

     一、Promise 核心概念
Promise 是什么?
Promise 是 JavaScript 中处理异步操作的对象,它表示一个异步操作的最终完成(或失败)及其结果值。

三种状态

  1. Pending(等待中):初始状态
  2. Fulfilled(已成功):操作成功完成
  3. Rejected(已失败):操作失败

状态转换图:

Pending → Fulfilled(执行 resolve)
Pending → Rejected(执行 reject)

     二、创建 Promise

const myPromise = new Promise((resolve, reject) => {
  // 异步操作(如 API 请求、定时器等)
  setTimeout(() => {
    const success = true; // 模拟操作结果
    
    if (success) {
      resolve("操作成功!"); // 状态变为 Fulfilled
    } else {
      reject("操作失败!"); // 状态变为 Rejected
    }
  }, 1000);
});

     三、then 方法详解
基本语法

promise.then(
  onFulfilled, // 成功回调函数(必选)
  onRejected   // 失败回调函数(可选)
);

特性

  1. 返回新的 Promise 对象,支持链式调用
  2. 接收两个回调函数参数:
    • onFulfilled:处理成功状态,接收 resolve 的值
    • onRejected:处理失败状态,接收 reject 的原因

     四、使用示例
基础用法

myPromise
  .then(
    result => {
      console.log("成功:", result); // 输出:成功: 操作成功!
      return "新的数据"; // 可返回新值
    },
    error => {
      console.error("失败:", error); // 失败时执行
      throw new Error("处理错误"); // 可抛出新错误
    }
  )
  .then(newResult => {
    console.log("链式调用:", newResult); // 输出:链式调用: 新的数据
  });

链式调用流程

[初始Promise]
   ↓
.then() → 返回 Promise1
   ↓
.then() → 返回 Promise2
   ↓
.catch() → 错误处理

     五、错误处理机制
推荐方式

fetchData()
  .then(handleSuccess)
  .then(processData)
  .catch(error => {
    console.error("捕获所有错误:", error);
  });

特殊场景处理

// 在特定步骤处理错误
fetchData()
  .then(
    result => process(result),
    specificError => handleSpecificError(specificError) // 只处理当前步骤错误
  )
  .catch(generalError => {
    console.error("通用错误处理:", generalError);
  });

     六、返回值处理规则

回调返回值类型then 返回的新 Promise 状态
普通值Fulfilled(值为返回值)
新的 Promise 对象跟随该 Promise 状态
抛出错误Rejected(值为错误对象)
无返回值(undefined)Fulfilled(值为 undefined)

示例

Promise.resolve(10)
  .then(x => x * 2)          // 返回 20 → Fulfilled
  .then(() => Promise.reject("错误")) // 返回 Rejected
  .then(() => { throw new Error("异常") }) // 被跳过
  .catch(e => console.log(e)); // 输出:"错误"

     七、高级技巧
1. 值穿透特性

Promise.resolve("原始值")
  .then() // 无回调函数
  .then(value => console.log(value)); // 输出:"原始值"

2. 同步返回处理

// then 回调可同步返回值
Promise.resolve()
  .then(() => "立即返回")
  .then(console.log); // 输出:"立即返回"

3. 异步操作组合

const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);

// 组合多个 Promise
p1.then(val1 => 
  p2.then(val2 => {
    console.log(val1 + val2); // 输出:3
    return val1 + val2;
  })
);

     八、Promise 静态方法

方法描述
Promise.resolve(x)创建已解决的 Promise
Promise.reject(err)创建已拒绝的 Promise
Promise.all([...])所有成功时返回结果数组
Promise.race([...])返回最先完成的 Promise 结果

示例

// 并行处理多个异步操作
Promise.all([
  fetch('/api/data1'),
  fetch('/api/data2')
])
.then(([result1, result2]) => {
  console.log("全部完成:", result1, result2);
})
.catch(error => {
  console.error("至少一个失败:", error);
});

     九、常见误区与解决方案
误区 1:忘记返回 Promise

// 错误:无法获取异步结果
fetchData()
  .then(data => {
    asyncProcess(data); // 忘记 return
  })
  .then(result => {
    // result 将是 undefined
  });

// 正确
.then(data => {
  return asyncProcess(data); // 显式返回
});

误区 2:错误处理不完整

// 错误:同步错误未被捕获
.then(data => {
  nonExistFunction(); // 抛出 ReferenceError
});

// 正确:始终添加 catch
.catch(console.error);

误区 3:Promise 嵌套地狱

// 避免这种嵌套
getUser().then(user => {
  getPosts(user.id).then(posts => {
    getComments(posts[0].id).then(comments => {
      // 深层嵌套...
    });
  });
});

// 改用链式调用
getUser()
  .then(user => getPosts(user.id))
  .then(posts => getComments(posts[0].id))
  .then(comments => { ... });

     十、最佳实践

  1. 始终返回结果:在 then 回调中 return 值或 Promise
  2. 使用 catch 结尾:在链式调用末尾添加错误处理
  3. 避免冗余嵌套:使用链式调用代替嵌套
  4. 合理拆分步骤:每个 then 只处理单一职责
  5. 处理同步错误:在 then 内部使用 try/catch
// 良好的 Promise 链示例
loadInitialData()
  .then(validateInput)
  .then(apiRequest)
  .then(processResponse)
  .then(updateUI)
  .catch(handleError);

     十一、与 async/await 的关系
Promise 是 async/await 的基础:

// async/await 本质是 Promise 语法糖
async function example() {
  try {
    const data = await myPromise; // 等待 Promise 解决
    const result = await process(data);
    return result;
  } catch (error) {
    handleError(error);
  }
}

总结

  • Promise:异步操作的容器,有三种状态
  • then 方法
    • 核心链式调用机制
    • 接收成功/失败回调
    • 返回新 Promise 对象
  • 关键特性
    • 值穿透
    • 错误冒泡
    • 链式流控制

掌握 Promise 和 then 方法,是处理 JavaScript 异步编程的基础,也是理解现代 async/await 语法的前提。通过合理的链式调用和错误处理,可以构建清晰可靠的异步代码流程。

















🤔 参考 14

JavaScript Promise 和 .then() 详解

     一、Promise 核心概念
Promise 是什么
Promise 是处理异步操作的对象,表示一个尚未完成但预期会完成的操作。它解决了传统回调函数的"回调地狱"问题。

三种状态

  1. Pending(待定):初始状态,操作尚未完成
  2. Fulfilled(已兑现):操作成功完成
  3. Rejected(已拒绝):操作失败

状态转换不可逆:Pending → FulfilledPending → Rejected

     二、创建 Promise

const myPromise = new Promise((resolve, reject) => {
  // 异步操作(如 API 请求、定时器等)
  const operationSucceeded = true; // 模拟操作结果
  
  if (operationSucceeded) {
    resolve("Success data"); // 状态变为 Fulfilled
  } else {
    reject("Error reason"); // 状态变为 Rejected
  }
});

     三、.then() 方法详解
.then() 是 Promise 的核心方法,用于处理异步操作的结果:

promise.then(
  onFulfilled,  // 成功回调(必需)
  onRejected    // 失败回调(可选)
);

基本用法

fetchData()
  .then(
    result => console.log("成功:", result),
    error => console.error("失败:", error)
  );

     四、.then() 的链式调用
Promise 的核心优势:链式调用(Chaining)

fetchUser() // 第一步:获取用户
  .then(user => fetchPosts(user.id)) // 第二步:获取用户帖子
  .then(posts => processPosts(posts)) // 第三步:处理帖子
  .then(finalResult => {
    console.log("最终结果:", finalResult);
  })
  .catch(error => {
    console.error("链中出错:", error);
  });

链式调用规则

  1. 每个 .then() 返回新 Promise
  2. 回调函数返回值决定新 Promise 状态:
    • 返回普通值 → 新 Promise 立即兑现
    • 返回 Promise → 继承该 Promise 状态
    • 抛出错误 → 新 Promise 拒绝

     五、错误处理
三种错误处理方式:

  1. .then() 的第二个参数

    promise.then(
      success => {...},
      error => { /* 只处理当前 Promise 的错误 */ }
    );
    
  2. .catch() 方法(推荐):

    promise
      .then(...)
      .catch(error => { 
        /* 捕获链中所有错误 */ 
      });
    
  3. try/catch 与 async/await

    async function handleData() {
      try {
        const data = await promise;
      } catch (error) {
        /* 处理错误 */
      }
    }
    

     六、Promise 静态方法

方法描述示例
Promise.resolve()创建已兑现的 PromisePromise.resolve(42)
Promise.reject()创建已拒绝的 PromisePromise.reject("Error")
Promise.all()所有成功才成功Promise.all([p1, p2])
Promise.race()第一个完成的结果Promise.race([p1, p2])
Promise.allSettled()等待所有完成Promise.allSettled([p1, p2])

     七、最佳实践

  1. 避免嵌套:使用链式调用代替嵌套

    // ❌ 避免
    firstPromise.then(result1 => {
      secondPromise(result1).then(result2 => ...)
    });
    
    // ✅ 推荐
    firstPromise
      .then(result1 => secondPromise(result1))
      .then(result2 => ...);
    
  2. 始终返回结果:在 .then() 中返回值或 Promise

    fetchData()
      .then(data => {
        // 处理数据...
        return processedData; // 重要!
      })
      .then(result => ...);
    
  3. 错误处理位置

    // ❌ 危险(可能遗漏错误)
    fetchData().then(handleSuccess);
    
    // ✅ 安全
    fetchData()
      .then(handleSuccess)
      .catch(handleError);
    

     八、Promise vs 回调函数

特性回调函数Promise
可读性嵌套难读链式清晰
错误处理需手动传递错误内置错误传播
组合能力困难Promise.all() 等
流程控制手动管理自动状态管理

     九、真实场景示例

function getUser(id) {
  return new Promise((resolve, reject) => {
    // 模拟 API 请求
    setTimeout(() => {
      resolve({ id, name: `User${id}` });
    }, 500);
  });
}

function getPosts(userId) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve([`Post1-${userId}`, `Post2-${userId}`]);
    }, 700);
  });
}

// 链式调用
getUser(1)
  .then(user => {
    console.log("获取用户:", user);
    return getPosts(user.id);
  })
  .then(posts => {
    console.log("获取帖子:", posts);
    return posts.length;
  })
  .then(count => {
    console.log(`帖子数量: ${count}`);
  })
  .catch(error => {
    console.error("处理失败:", error);
  });

     十、常见陷阱

  1. 忘记返回 Promise

    // ❌ 错误:第二个 then 接收 undefined
    fetchData()
      .then(data => { process(data) }) // 缺少 return
      .then(result => ...)
    
  2. 错误处理不完整

    // ❌ 可能遗漏同步错误
    new Promise(() => {
      throw new Error("同步错误"); // 未捕获!
    });
    
  3. 混合回调与 Promise

    // ❌ 反模式
    function fetchData(callback) {
      return new Promise(resolve => {
        doAsyncThing(() => {
          callback(); // 同时使用两种模式
          resolve();
        });
      });
    }
    

     总结表格

概念作用关键特性
Promise封装异步操作状态机(Pending/Fulfilled/Rejected)
.then()处理异步结果链式调用、返回新 Promise
链式调用管理异步流程通过返回值传递结果
.catch()错误处理捕获链中所有错误
静态方法多 Promise 处理all/race/allSettled

黄金法则

  1. 每个 .then() 应该返回新值或 Promise
  2. 始终在链式调用末尾添加 .catch()
  3. 使用 Promise 替代回调嵌套
  4. 对同步错误使用 try/catch,异步错误用 .catch()

















🤔 参考 15

JavaScript Promise 和 then 方法详解

在 JavaScript 中,Promise 是处理异步操作的核心机制,而 then() 方法是使用 Promise 的关键。下面我将详细解释这些概念,并通过一个可视化示例展示它们的工作原理。

核心概念解析

     Promise 是什么?
Promise 是一个表示异步操作最终完成(或失败)及其结果值的对象。它有三种状态:

  • Pending(等待中):初始状态
  • Fulfilled(已成功):操作成功完成
  • Rejected(已失败):操作失败

     then() 方法
then() 方法用于处理 Promise 的结果:

  • 接受两个参数(都是可选的):
    • onFulfilled:Promise 成功时的回调函数
    • onRejected:Promise 失败时的回调函数
  • 返回一个新的 Promise,支持链式调用
promise.then(
  result => { /* 处理成功结果 */ },
  error => { /* 处理错误 */ }
);

可视化示例

下面是一个交互式演示,展示 Promise 和 then 方法的工作原理:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JavaScript Promise 和 then 详解</title>
    <style>
        :root {
            --primary: #3498db;
            --success: #2ecc71;
            --danger: #e74c3c;
            --gray: #ecf0f1;
            --dark: #34495e;
        }
        
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            line-height: 1.6;
            color: #333;
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
            background-color: #f9f9f9;
        }
        
        h1 {
            color: var(--dark);
            text-align: center;
            margin-bottom: 30px;
            border-bottom: 2px solid var(--primary);
            padding-bottom: 15px;
        }
        
        .container {
            display: flex;
            flex-wrap: wrap;
            gap: 30px;
        }
        
        .explanation {
            flex: 1;
            min-width: 300px;
            background: white;
            border-radius: 8px;
            padding: 20px;
            box-shadow: 0 4px 8px rgba(0,0,0,0.1);
        }
        
        .demo {
            flex: 1;
            min-width: 300px;
            background: white;
            border-radius: 8px;
            padding: 20px;
            box-shadow: 0 4px 8px rgba(0,0,0,0.1);
            display: flex;
            flex-direction: column;
            gap: 15px;
        }
        
        .code-block {
            background: #2d2d2d;
            color: #f8f8f2;
            padding: 15px;
            border-radius: 5px;
            font-family: 'Consolas', monospace;
            overflow-x: auto;
            margin: 15px 0;
        }
        
        .promise-state {
            display: flex;
            justify-content: space-around;
            margin: 20px 0;
        }
        
        .state {
            padding: 10px 20px;
            border-radius: 20px;
            background: var(--gray);
            color: #7f8c8d;
            font-weight: bold;
            transition: all 0.3s ease;
        }
        
        .state.active {
            background: var(--primary);
            color: white;
            transform: scale(1.05);
            box-shadow: 0 4px 8px rgba(52, 152, 219, 0.3);
        }
        
        .state.success {
            background: var(--success);
            color: white;
        }
        
        .state.failure {
            background: var(--danger);
            color: white;
        }
        
        .promise-chain {
            display: flex;
            flex-direction: column;
            gap: 20px;
            margin-top: 20px;
        }
        
        .promise-step {
            background: var(--gray);
            padding: 15px;
            border-radius: 8px;
            position: relative;
            transition: all 0.3s ease;
        }
        
        .promise-step.active {
            background: var(--primary);
            color: white;
            transform: translateX(10px);
        }
        
        .promise-step.success {
            background: var(--success);
            color: white;
        }
        
        .promise-step.failure {
            background: var(--danger);
            color: white;
        }
        
        .controls {
            display: flex;
            gap: 10px;
            flex-wrap: wrap;
            margin-top: 20px;
        }
        
        button {
            padding: 10px 20px;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-weight: bold;
            transition: all 0.2s;
            background: var(--primary);
            color: white;
        }
        
        button:hover {
            opacity: 0.9;
            transform: translateY(-2px);
        }
        
        button:disabled {
            background: #bdc3c7;
            cursor: not-allowed;
            transform: none;
        }
        
        button.success {
            background: var(--success);
        }
        
        button.danger {
            background: var(--danger);
        }
        
        .result {
            margin-top: 20px;
            padding: 15px;
            border-radius: 8px;
            background: var(--gray);
            min-height: 50px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: bold;
        }
        
        .result-value {
            color: var(--primary);
            margin-left: 5px;
        }
        
        .arrow {
            text-align: center;
            font-size: 24px;
            color: #7f8c8d;
        }
        
        .chain-title {
            text-align: center;
            margin: 10px 0;
            font-weight: bold;
            color: var(--dark);
        }
        
        .highlight {
            background: #fff9c4;
            padding: 2px 4px;
            border-radius: 3px;
        }
    </style>
</head>
<body>
    <h1>JavaScript Promise 和 then 方法详解</h1>
    
    <div class="container">
        <div class="explanation">
            <h2>Promise 基础</h2>
            <p>Promise 是 JavaScript 中处理异步操作的对象,它代表一个可能现在、将来或永不可能可用的值。</p>
            
            <h3>创建 Promise</h3>
            <div class="code-block">
const promise = new Promise((resolve, reject) => {
    // 异步操作
    if (/* 操作成功 */) {
        resolve(value); // 状态变为 fulfilled
    } else {
        reject(error); // 状态变为 rejected
    }
});
            </div>
            
            <h3>Promise 状态</h3>
            <div class="promise-state">
                <div class="state" id="state-pending">Pending</div>
                <div class="state" id="state-fulfilled">Fulfilled</div>
                <div class="state" id="state-rejected">Rejected</div>
            </div>
            
            <h3>then() 方法</h3>
            <p><span class="highlight">then()</span> 方法用于处理 Promise 的结果:</p>
            <div class="code-block">
promise.then(
    result => { /* 处理成功 */ },
    error => { /* 处理失败 */ }
);
            </div>
            
            <p><span class="highlight">then()</span> 返回一个新的 Promise,支持链式调用:</p>
            <div class="code-block">
promise
    .then(step1)
    .then(step2)
    .then(step3)
    .catch(error => { /* 处理链中任何错误 */ });
            </div>
            
            <h3>关键特性</h3>
            <ul>
                <li>Promise 状态一旦改变(fulfilled 或 rejected),就不可再变</li>
                <li>then() 方法总是异步执行,即使 Promise 已经解决</li>
                <li>链式调用中,每个 then() 接收前一个 then() 的返回值</li>
                <li>错误会沿着链向下传播,直到被 catch() 捕获</li>
            </ul>
        </div>
        
        <div class="demo">
            <h2>Promise 链式调用演示</h2>
            
            <div class="controls">
                <button id="btn-start" class="success">启动 Promise</button>
                <button id="btn-success" disabled>操作成功</button>
                <button id="btn-fail" disabled>操作失败</button>
                <button id="btn-reset">重置</button>
            </div>
            
            <div class="chain-title">Promise 执行链</div>
            <div class="promise-chain">
                <div class="promise-step" id="step1">创建 Promise(初始状态)</div>
                <div class="arrow"></div>
                <div class="promise-step" id="step2">第一个 then() 处理</div>
                <div class="arrow"></div>
                <div class="promise-step" id="step3">第二个 then() 处理</div>
                <div class="arrow"></div>
                <div class="promise-step" id="step4">catch() 错误处理</div>
            </div>
            
            <div class="result">
                当前结果: <span class="result-value" id="result-value">等待开始...</span>
            </div>
        </div>
    </div>

    <script>
        // DOM 元素引用
        const statePending = document.getElementById('state-pending');
        const stateFulfilled = document.getElementById('state-fulfilled');
        const stateRejected = document.getElementById('state-rejected');
        
        const step1 = document.getElementById('step1');
        const step2 = document.getElementById('step2');
        const step3 = document.getElementById('step3');
        const step4 = document.getElementById('step4');
        const resultValue = document.getElementById('result-value');
        
        const btnStart = document.getElementById('btn-start');
        const btnSuccess = document.getElementById('btn-success');
        const btnFail = document.getElementById('btn-fail');
        const btnReset = document.getElementById('btn-reset');
        
        let demoPromise;
        let resolvePromise;
        let rejectPromise;
        
        // 重置所有状态
        function resetDemo() {
            statePending.classList.remove('active');
            stateFulfilled.classList.remove('active', 'success');
            stateRejected.classList.remove('active', 'failure');
            
            step1.classList.remove('active', 'success', 'failure');
            step2.classList.remove('active', 'success', 'failure');
            step3.classList.remove('active', 'success', 'failure');
            step4.classList.remove('active', 'success', 'failure');
            
            step1.textContent = "创建 Promise(初始状态)";
            step2.textContent = "第一个 then() 处理";
            step3.textContent = "第二个 then() 处理";
            step4.textContent = "catch() 错误处理";
            
            resultValue.textContent = "等待开始...";
            
            btnStart.disabled = false;
            btnSuccess.disabled = true;
            btnFail.disabled = true;
        }
        
        // 启动 Promise
        function startPromise() {
            resetDemo();
            
            // 设置初始状态
            statePending.classList.add('active');
            step1.classList.add('active');
            resultValue.textContent = "Promise 创建,状态: Pending";
            
            btnStart.disabled = true;
            btnSuccess.disabled = false;
            btnFail.disabled = false;
            
            // 创建新的 Promise
            demoPromise = new Promise((resolve, reject) => {
                resolvePromise = resolve;
                rejectPromise = reject;
            });
            
            // 链式调用
            demoPromise
                .then(result => {
                    // 第一个 then 处理
                    step1.classList.remove('active');
                    step1.classList.add('success');
                    step1.textContent = `初始 Promise 成功: ${result}`;
                    
                    step2.classList.add('active');
                    resultValue.textContent = `第一个 then() 执行,输入: ${result}`;
                    
                    // 返回新值给下一个 then
                    return `${result} -> 经过第一个 then 处理`;
                })
                .then(result => {
                    // 模拟一个可能成功或失败的操作
                    return new Promise((resolve, reject) => {
                        step2.classList.remove('active');
                        step2.classList.add('success');
                        step2.textContent = `第一个 then() 成功: ${result}`;
                        
                        step3.classList.add('active');
                        resultValue.textContent = `第二个 then() 执行,输入: ${result}`;
                        
                        // 这里我们总是成功,但实际中可能根据条件 resolve 或 reject
                        resolve(`${result} -> 经过第二个 then 处理`);
                    });
                })
                .then(result => {
                    // 第三个 then 处理(成功路径)
                    step3.classList.remove('active');
                    step3.classList.add('success');
                    step3.textContent = `第二个 then() 成功: ${result}`;
                    
                    resultValue.textContent = `最终结果: ${result}`;
                    return result;
                })
                .catch(error => {
                    // 错误处理
                    step4.classList.add('active', 'failure');
                    step4.textContent = `捕获到错误: ${error}`;
                    
                    resultValue.textContent = `错误结果: ${error}`;
                    return error;
                });
        }
        
        // 事件监听
        btnStart.addEventListener('click', startPromise);
        btnReset.addEventListener('click', resetDemo);
        
        btnSuccess.addEventListener('click', () => {
            statePending.classList.remove('active');
            stateFulfilled.classList.add('active', 'success');
            resolvePromise("初始操作成功!");
        });
        
        btnFail.addEventListener('click', () => {
            statePending.classList.remove('active');
            stateRejected.classList.add('active', 'failure');
            step1.classList.remove('active');
            step1.classList.add('failure');
            step1.textContent = "初始 Promise 失败";
            
            // 模拟一个失败操作
            rejectPromise("初始操作失败!");
        });
        
        // 初始化
        resetDemo();
    </script>
</body>
</html>

关键概念详解

     Promise 的创建

const promise = new Promise((resolve, reject) => {
  // 异步操作(如 API 请求、定时器等)
  if (/* 操作成功 */) {
    resolve(result); // 将状态改为 fulfilled
  } else {
    reject(error); // 将状态改为 rejected
  }
});

     then() 方法的特点

  1. 链式调用:每个 then() 返回一个新的 Promise
  2. 值传递:前一个处理函数的返回值会传递给下一个 then()
  3. 错误传播:错误会沿着链向下传播,直到被捕获
  4. 异步执行:即使 Promise 已经解决,then() 回调也是异步执行的

     Promise 链示例

fetchData()
  .then(data => {
    console.log("第一步:", data);
    return processData(data); // 返回新值或新Promise
  })
  .then(processedData => {
    console.log("第二步:", processedData);
    return saveData(processedData);
  })
  .then(saveResult => {
    console.log("第三步: 保存成功", saveResult);
  })
  .catch(error => {
    console.error("链中发生错误:", error);
  });

     最佳实践

  1. 总是返回结果:在 then() 中返回一个值或 Promise,以保持链式调用
  2. 使用 catch 处理错误:在链的末尾添加 catch() 捕获所有错误
  3. 避免嵌套:使用链式调用代替嵌套的 then()
  4. 处理 finally:使用 finally() 执行清理操作,无论成功失败都会执行

通过这个详细解释和可视化示例,您应该对 JavaScript 的 Promise 和 then() 方法有了更深入的理解。您可以直接复制上面的 HTML 代码到文件中运行,通过交互式演示来观察 Promise 状态变化和链式调用的过程。

















🤔 参考 16

JavaScript Promise 和 then() 方法详解

一、Promise 核心概念

     1. Promise 的基本结构

const promise = new Promise((resolve, reject) => {
  // 异步操作
  if (/* 操作成功 */) {
    resolve(value); // 将状态改为 fulfilled
  } else {
    reject(error); // 将状态改为 rejected
  }
});

     2. Promise 的状态

  • pending: 初始状态,既不是成功也不是失败
  • fulfilled: 操作成功完成
  • rejected: 操作失败

状态一旦改变就不可逆,且只能从 pending → fulfilled 或 pending → rejected。

二、then() 方法详解

     1. then() 的基本用法

promise.then(
  onFulfilled?, // 成功回调
  onRejected?   // 失败回调
);

     2. then() 的特性

  1. 返回新 Promise:每次调用 then() 都会返回一个新的 Promise
  2. 值穿透:如果 then() 的回调不是函数,会忽略该处理程序,值会"穿透"到下一个链
  3. 异步执行:即使 Promise 立即 resolved,回调也会被放入微任务队列

     3. then() 的参数

  • onFulfilled:当 Promise 变为 fulfilled 时调用的函数,接收 resolved 的值
  • onRejected:当 Promise 变为 rejected 时调用的函数,接收 rejected 的原因
promise.then(
  value => {
    // 成功处理
  },
  reason => {
    // 失败处理
  }
);

三、then() 的链式调用

     1. 基本链式调用

fetchData()
  .then(data => processData(data))
  .then(processedData => displayData(processedData))
  .then(result => console.log('完成:', result))
  .catch(error => console.error('出错:', error));

     2. 链式调用的工作原理

  1. 每个 then() 返回一个新 Promise
  2. 下一个 then() 的回调等待前一个 Promise 完成
  3. 回调函数的返回值决定下一个 Promise 的状态:
    • 返回普通值 → 新 Promise 用该值 resolved
    • 返回 Promise → 新 Promise 跟随该 Promise 的状态
    • 抛出错误 → 新 Promise 用该错误 rejected

     3. 链式调用示例

new Promise((resolve) => resolve(1))
  .then(value => {
    console.log(value); // 1
    return value + 1;
  })
  .then(value => {
    console.log(value); // 2
    return new Promise(resolve => setTimeout(() => resolve(value + 1), 1000));
  })
  .then(value => {
    console.log(value); // 3 (1秒后)
    throw new Error('出错了');
  })
  .then(
    value => console.log('这不会执行', value),
    error => {
      console.log('捕获错误:', error.message); // 捕获错误: 出错了
      return '错误已处理';
    }
  )
  .then(value => console.log('继续执行:', value)); // 继续执行: 错误已处理

四、then() 与 catch() 的关系

     1. catch() 本质

promise.catch(onRejected);
// 等价于
promise.then(null, onRejected);

     2. 错误处理最佳实践

推荐在链式调用末尾使用一个 catch(),而不是在每个 then() 中都提供错误处理:

// 不好 - 重复错误处理
promise
  .then(fn1, handleError)
  .then(fn2, handleError)
  .then(fn3, handleError);

// 好 - 集中错误处理
promise
  .then(fn1)
  .then(fn2)
  .then(fn3)
  .catch(handleError);

     3. 为什么这样更好?

  1. 避免代码重复
  2. 可以捕获前面所有步骤的错误
  3. 更清晰的代码结构

五、then() 的返回值

     1. 返回普通值

Promise.resolve(1)
  .then(value => {
    console.log(value); // 1
    return value + 1; // 返回普通值
  })
  .then(value => {
    console.log(value); // 2
  });

     2. 返回 Promise

Promise.resolve(1)
  .then(value => {
    console.log(value); // 1
    return Promise.resolve(value + 1); // 返回 Promise
  })
  .then(value => {
    console.log(value); // 2
  });

     3. 抛出错误

Promise.resolve(1)
  .then(value => {
    console.log(value); // 1
    throw new Error('出错了');
  })
  .then(
    value => console.log('这不会执行', value),
    error => {
      console.log('捕获错误:', error.message); // 捕获错误: 出错了
      return '错误已修复';
    }
  )
  .then(value => console.log('继续:', value)); // 继续: 错误已修复

六、then() 的执行时机

     1. 微任务队列

Promise 回调是微任务,会在当前执行栈清空后立即执行,比宏任务(如 setTimeout)优先级高。

console.log('开始');

Promise.resolve()
  .then(() => console.log('Promise 回调'));

setTimeout(() => console.log('setTimeout 回调'), 0);

console.log('结束');

// 输出顺序:
// 开始
// 结束
// Promise 回调
// setTimeout 回调

     2. 异步性保证

即使 Promise 已经 resolved,通过 then() 注册的回调仍然是异步执行的:

const promise = Promise.resolve();
promise.then(() => console.log('立即 resolved,但异步执行'));
console.log('这先执行');

七、常见问题与解决方案

     1. 问题:回调地狱

解决方案:使用链式 then() 或 async/await

// 回调地狱
doSomething(function(result) {
  doSomethingElse(result, function(newResult) {
    doThirdThing(newResult, function(finalResult) {
      console.log(finalResult);
    });
  });
});

// Promise 链式调用
doSomething()
  .then(result => doSomethingElse(result))
  .then(newResult => doThirdThing(newResult))
  .then(finalResult => console.log(finalResult));

// async/await
async function process() {
  const result = await doSomething();
  const newResult = await doSomethingElse(result);
  const finalResult = await doThirdThing(newResult);
  console.log(finalResult);
}

     2. 问题:错误处理不当

解决方案:确保错误被捕获

// 错误示例 - 第二个错误未被捕获
doSomething()
  .then(result => doSomethingElse(result))
  .then(newResult => doThirdThing(newResult))
  .then(finalResult => console.log(finalResult))
  .catch(error => console.error('第一个错误:', error));

// 正确示例 - 所有错误都被捕获
doSomething()
  .then(result => {
    return doSomethingElse(result);
  })
  .then(newResult => {
    return doThirdThing(newResult);
  })
  .then(finalResult => {
    console.log(finalResult);
  })
  .catch(error => {
    console.error('任何步骤的错误:', error);
  });

     3. 问题:忘记返回值

解决方案:确保链式调用中每个步骤都返回

// 错误示例 - 第二个 then 不会接收到值
getData()
  .then(data => {
    processData(data); // 忘记 return
  })
  .then(processedData => {
    // processedData 是 undefined
  });

// 正确示例
getData()
  .then(data => {
    return processData(data); // 明确返回
  })
  .then(processedData => {
    // 正确接收到处理后的数据
  });

八、高级用法

     1. Promise 链中的条件分支

getUser()
  .then(user => {
    if (!user.isPremium) {
      return 'standard'; // 非高级用户直接返回
    }
    return getPremiumFeatures() // 高级用户获取额外功能
      .then(features => {
        return {
          ...user,
          features
        };
      });
  })
  .then(result => {
    // result 可能是字符串 'standard' 或合并后的对象
  });

     2. 动态 Promise 链

function processInSequence(tasks, initialValue) {
  return tasks.reduce((promiseChain, currentTask) => {
    return promiseChain.then(currentTask);
  }, Promise.resolve(initialValue));
}

const tasks = [
  value => value + 1,
  value => new Promise(resolve => setTimeout(() => resolve(value * 2), 1000)),
  value => value.toString()
];

processInSequence(tasks, 1)
  .then(result => console.log(result)); // 约1秒后输出 "4"

九、总结

  1. then() 是 Promise 的核心方法,用于处理 resolved 和 rejected 状态
  2. 链式调用是 then() 的强大特性,可以创建清晰的异步流程
  3. 返回值决定下一个 Promise 的状态,可以是普通值、Promise 或错误
  4. 错误处理应该集中进行,通常在链式调用的末尾使用 catch()
  5. then() 回调是微任务,保证异步执行但优先级高于宏任务

掌握 then() 的这些细节,可以让你写出更清晰、更可靠的异步 JavaScript 代码。

















🤔 参考 17

好的,我们来深入详细地解析 JavaScript 中的 Promise.then() 方法。它们是处理异步操作的核心机制,是现代 JavaScript 开发的基石。


1. Promise:异步操作的“未来凭证”

核心思想:
Promise 是一个对象,它代表一个当前尚未完成,但未来某个时刻会完成的异步操作的结果。你可以把它想象成一张“收据”或“承诺书”,它保证未来会给你一个结果(成功或失败),让你可以提前安排好“拿到结果后该做什么”。

Promise 的三种状态:

  • Pending (等待中): 初始状态。异步操作正在进行,结果尚未确定。
  • Fulfilled (已兑现/成功): 异步操作成功完成。Promise 被 resolve 函数处理。
  • Rejected (已拒绝/失败): 异步操作失败。Promise 被 reject 函数处理。

状态的核心特点:

  1. 单向性: 状态只能从 Pending 变为 FulfilledRejected
  2. 不可逆性: 状态一旦改变,就永远不会再变。一个 Promise 只能成功一次或失败一次。
  3. 确定性: 一个 Promise 实例最终必然处于 FulfilledRejected 状态之一。

创建 Promise:

使用 new Promise() 构造函数。

const myPromise = new Promise((resolve, reject) => {
    // 执行异步操作
    // 例如:setTimeout, fetch API, 文件读取等

    // 模拟一个异步操作(比如网络请求)
    setTimeout(() => {
        const success = Math.random() > 0.5; // 50% 成功率,模拟随机性
        if (success) {
            // 操作成功,调用 resolve,并传递成功的结果数据
            resolve("数据获取成功!这里是数据内容");
        } else {
            // 操作失败,调用 reject,并传递一个错误对象
            reject(new Error("网络请求超时或出错"));
        }
    }, 2000); // 模拟2秒的延迟
});

// myPromise 现在是一个 Promise 对象,初始状态为 Pending
// 它代表了这个2秒后才会完成的异步操作

Promise 的关键点:

  • resolvereject 是由 JavaScript 引擎提供的函数,你只需要在适当的时机调用它们。
  • resolve() 的参数会成为 .then() 中成功回调的参数。
  • reject() 的参数(通常是一个 Error 对象)会成为 .then().catch() 中失败回调的参数。

2. .then() :处理 Promise 结果的“处理器”

.then() 方法是 Promise 实例的核心方法,用于指定当 Promise 状态变为 FulfilledRejected 时,应该执行的回调函数。

语法:

promise.then(onFulfilled, onRejected);
  • onFulfilled (必需): 一个函数。当 Promise 状态变为 Fulfilled 时,该函数会被调用。它接收 resolve() 传递的值作为其唯一参数。
  • onRejected (可选): 一个函数。当 Promise 状态变为 Rejected 时,该函数会被调用。它接收 reject() 传递的错误对象作为其唯一参数。

基本用法示例:

myPromise
    .then(
        (data) => { // onFulfilled 回调 - 处理成功
            console.log("成功:", data); // 2秒后输出: "成功: 数据获取成功!这里是数据内容"
            // 在这里可以处理获取到的数据,比如更新UI
        },
        (error) => { // onRejected 回调 - 处理失败
            console.error("失败:", error.message); // 2秒后输出: "失败: 网络请求超时或出错"
            // 在这里可以处理错误,比如显示错误提示
        }
    );

.then() 的返回值:链式调用的关键

.then() 方法本身返回一个全新的 Promise 对象!这个新 Promise 的状态和值,完全取决于其回调函数(onFulfilledonRejected)的执行结果。这是实现 Promise 链式调用的基础。

返回值规则详解:

  1. 回调函数返回一个普通值 (非 Promise):

    • 新返回的 Promise 状态变为 Fulfilled
    • 其值就是回调函数返回的那个值。
    myPromise
        .then((data) => {
            console.log(data);
            return "经过处理的数据"; // 返回一个普通字符串
        })
        .then((processedData) => {
            console.log("下个 then 收到:", processedData); // 输出: "下个 then 收到: 经过处理的数据"
        });
    
  2. 回调函数返回一个 Promise 对象:

    • 新返回的 Promise 的状态和值,将跟随这个返回的 Promise。
    • 这是实现异步操作顺序执行的关键!
    function fetchUserData(userId) {
        return new Promise((resolve) => {
            setTimeout(() => resolve({ id: userId, name: "Alice" }), 1000);
        });
    }
    
    function fetchUserOrders(userInfo) {
        return new Promise((resolve) => {
            setTimeout(() => resolve([{ orderId: 1, product: "Laptop" }]), 1000);
        });
    }
    
    // 模拟获取用户ID -> 获取用户信息 -> 获取订单信息
    myPromise // 假设 myPromise resolve 出 userId
        .then((userId) => {
            console.log("用户ID:", userId);
            return fetchUserData(userId); // 返回一个新的 Promise
            // 当 fetchUserData 完成,其结果会传递给下一个 .then
        })
        .then((userInfo) => {
            console.log("用户信息:", userInfo);
            return fetchUserOrders(userInfo); // 再返回一个新的 Promise
        })
        .then((orders) => {
            console.log("用户订单:", orders);
        });
    
  3. 回调函数抛出一个错误 (throw error):

    • 新返回的 Promise 状态变为 Rejected
    • 其原因为抛出的错误。
    myPromise
        .then((data) => {
            throw new Error("处理数据时出错"); // 在成功回调里抛出错误
        })
        .then(
            null,
            (error) => {
                console.log("错误被捕获:", error.message); // 输出: "错误被捕获: 处理数据时出错"
            }
        );
    
  4. 回调函数不返回任何值 (隐式返回 undefined):

    • 新返回的 Promise 状态变为 Fulfilled
    • 其值为 undefined

链式调用的优势:

  • 避免回调地狱 (Callback Hell): 传统的嵌套回调(callback(callback(callback(...))))会导致代码难以阅读和维护。.then() 的链式调用让异步代码线性化,逻辑更清晰。
  • 错误冒泡与集中处理: 如果链中任何一个 .then() 的回调抛出错误,或者其返回的 Promise 被 reject,这个错误会沿着链向后传递,直到被 .catch() 捕获。

3. .catch().finally()

虽然你问的是 .then(),但这两个方法与 .then() 紧密相关,是处理 Promise 的完整工具集。

  • .catch(onRejected):

    • 专门用于处理 Promise 链中任何步骤的 Rejected 状态或抛出的错误。
    • 语法上等价于 .then(null, onRejected)
    • 强烈推荐在 Promise 链的末尾使用 .catch() 来集中处理所有可能的错误。
    myPromise
        .then((data) => { /* 处理成功 */ })
        .then((moreData) => { /* 处理更多成功 */ })
        .catch((error) => { // 集中捕获前面所有 .then 中可能发生的错误
            console.error("链式调用中出错:", error);
        });
    
  • .finally(onFinally):

    • 无论 Promise 最终是 Fulfilled 还是 Rejected,只要状态确定,onFinally 回调都会执行。
    • 常用于执行清理工作,如关闭加载动画、释放资源等。
    • onFinally 回调不接收任何参数,且其返回值会被忽略。
    myPromise
        .then((data) => { /* ... */ })
        .catch((error) => { /* ... */ })
        .finally(() => {
            console.log("异步操作结束,清理工作。");
            // 例如: hideLoadingSpinner();
        });
    

总结

  • Promise 是一个表示异步操作最终结果的对象,有 PendingFulfilledRejected 三种状态,状态一旦改变不可逆。
  • .then() 是处理 Promise 结果的方法,接收成功和失败的回调。
  • .then() 返回一个新的 Promise,这是实现链式调用的基础,让复杂的异步流程变得清晰有序。
  • 链式调用的返回值规则(返回值、返回 Promise、抛出错误)是理解异步流程控制的关键。
  • .catch() 用于集中处理错误,.finally() 用于执行最终清理。

理解 Promise 和 .then() 是掌握现代 JavaScript 异步编程(如 async/await)的基石。它们将“未来才会有的结果”变成了可以提前规划和处理的对象,极大地提升了异步代码的可读性和可维护性。

















🤔 参考 18

JavaScript 中的 Promise 与 then 方法详解

在 JavaScript 中,Promise 是处理异步操作的重要机制,而 then 方法则是 Promise 实现链式异步操作的核心。它们共同解决了传统回调函数嵌套导致的"回调地狱"问题,让异步代码更具可读性和可维护性。

一、Promise:异步操作的容器

Promise 是一个对象,用于表示一个异步操作的最终完成(或失败)及其结果值。它就像一个"承诺",承诺在未来某个时间点会给出操作结果。

     1. Promise 的三种状态

  • pending(进行中):初始状态,异步操作尚未完成
  • fulfilled(已成功):异步操作完成并返回结果,状态不可逆
  • rejected(已失败):异步操作出错,状态不可逆

状态只能从 pending 转变为 fulfilledrejected,一旦转变就会永久保持该状态(“已敲定”)。

     2. 创建 Promise
通过 new Promise() 构造函数创建,接收一个执行器函数(executor),该函数有两个参数:

  • resolve:异步操作成功时调用,将状态改为 fulfilled 并传递结果
  • reject:异步操作失败时调用,将状态改为 rejected 并传递错误
// 示例:创建一个模拟网络请求的 Promise
const fetchData = new Promise((resolve, reject) => {
  // 模拟异步操作(如 AJAX 请求)
  setTimeout(() => {
    const success = Math.random() > 0.3; // 70% 概率成功
    if (success) {
      resolve({ id: 1, name: "示例数据" }); // 成功时传递结果
    } else {
      reject(new Error("网络请求失败")); // 失败时传递错误
    }
  }, 1000);
});

     3. Promise 的核心优势

  • 解决回调嵌套问题,将异步操作扁平化
  • 提供统一的异步操作处理接口
  • 支持多个异步操作的串行或并行处理

二、then 方法:处理 Promise 结果

then 是 Promise 原型上的方法,用于指定 Promise 状态变化后的回调函数,是实现链式调用的关键。

     1. 基本语法

promise.then(onFulfilled, onRejected);
  • onFulfilled(可选):当 Promise 变为 fulfilled 时调用,接收 resolve 传递的结果
  • onRejected(可选):当 Promise 变为 rejected 时调用,接收 reject 传递的错误
// 处理前面创建的 fetchData
fetchData
  .then(
    (data) => { console.log("成功获取数据:", data); },
    (error) => { console.log("获取数据失败:", error.message); }
  );

     2. 链式调用的魔力
then 方法返回一个新的 Promise 对象,这使得我们可以链式调用多个 then,实现异步操作的顺序执行:

// 示例:链式处理多个异步操作
fetchUser() // 步骤1:获取用户信息(返回 Promise)
  .then(user => {
    console.log("获取用户:", user);
    return fetchPosts(user.id); // 步骤2:用用户ID获取文章(返回新 Promise)
  })
  .then(posts => {
    console.log("获取文章:", posts);
    return fetchComments(posts[0].id); // 步骤3:用文章ID获取评论
  })
  .then(comments => {
    console.log("获取评论:", comments);
  })
  .catch(error => { // 捕获整个链中的错误
    console.log("操作出错:", error);
  });

     3. 链式调用的工作原理

  • 前一个 then 的返回值会作为后一个 then 的输入
  • 如果返回的是普通值,直接传递给下一个 then
  • 如果返回的是 Promise,下一个 then 会等待该 Promise 状态变化后再执行
  • 如果抛出异常(throw),会触发下一个错误处理函数
// then 方法返回值示例
Promise.resolve(1)
  .then(num => {
    return num * 2; // 返回普通值
  })
  .then(num => {
    return new Promise(resolve => resolve(num * 2)); // 返回 Promise
  })
  .then(num => {
    console.log(num); // 输出:4
    throw new Error("故意出错"); // 抛出异常
  })
  .then(
    () => console.log("不会执行"),
    (error) => console.log("捕获错误:", error.message) // 输出错误信息
  );

     4. 错误处理
除了 then 的第二个参数,更推荐使用 catch 方法统一捕获错误,它本质上是 then(null, onRejected) 的语法糖:

// 推荐的错误处理方式
fetchData
  .then(data => {
    console.log("处理数据:", data);
    // 可能发生错误的操作
    if (!data.name) {
      throw new Error("数据格式错误");
    }
  })
  .catch(error => {
    // 会捕获:
    // 1. fetchData 的 reject
    // 2. then 中抛出的异常
    console.log("错误处理:", error.message);
  });

三、Promise 常用静态方法

  • Promise.resolve(value):快速创建一个已成功的 Promise
  • Promise.reject(error):快速创建一个已失败的 Promise
  • Promise.all(iterable):等待所有 Promise 成功,返回结果数组;只要有一个失败就立即失败
  • Promise.race(iterable):返回第一个状态变化的 Promise 的结果
// Promise.all 示例:并行处理多个异步操作
const promise1 = fetch("/api/user");
const promise2 = fetch("/api/posts");
const promise3 = fetch("/api/comments");

Promise.all([promise1, promise2, promise3])
  .then(results => {
    console.log("所有请求完成:", results);
  })
  .catch(error => {
    console.log("有一个请求失败:", error);
  });

四、总结

  • Promise 是异步操作的容器,通过状态管理异步结果
  • then 方法是 Promise 实现链式调用的核心,返回新的 Promise 使异步操作可串联
  • 链式调用解决了回调嵌套问题,让异步代码更清晰
  • catch 方法用于统一捕获 Promise 链中的所有错误
  • Promise 静态方法(如 allrace)方便处理多个异步操作

理解 Promise 和 then 方法是掌握 JavaScript 异步编程的基础,也是学习 async/await 语法的前提。在实际开发中,它们广泛应用于网络请求、定时器、文件操作等所有异步场景。

















🤔 参考 19

JavaScript 的 Promise.then() 是异步编程的核心机制,用于管理异步操作的状态和结果处理。以下从原理到实践的详解:


     ⚙️ 一、Promise 的核心概念

  1. Promise 是什么?
    Promise 是一个表示异步操作最终状态(成功/失败)的对象,用于解耦异步操作与结果处理逻辑。它有三种不可逆状态:

    • Pending(等待中):初始状态,操作未完成。
    • Fulfilled(已成功):操作成功完成,由 resolve() 触发。
    • Rejected(已失败):操作失败,由 reject() 触发。
  2. 创建 Promise
    通过 new Promise(executor) 创建实例,executor 函数接收 resolvereject 两个参数:

    const promise = new Promise((resolve, reject) => {
      setTimeout(() => {
        Math.random() > 0.5 ? resolve("成功") : reject("失败");
      }, 1000);
    });
    

     🔗 二、 .then() 方法详解
.then() 是 Promise 的核心方法,用于注册成功/失败的回调,并返回新 Promise 支持链式调用。

  1. 基本语法

    promise.then(
      (value) => { /* 成功处理 */ }, // onFulfilled
      (error) => { /* 失败处理 */ }  // onRejected(可选)
    );
    
    • 若省略 onRejected 参数,错误会沿链传递到后续 .catch()
  2. 链式调用机制
    每个 .then() 返回的新 Promise 状态由回调函数的返回值决定:

    • 返回普通值:新 Promise 立即成功(value 作为结果)。
    • 返回新 Promise:新 Promise 跟随其状态。
    • 抛出错误:新 Promise 立即失败。
    fetchData()
      .then(data => process(data))  // 返回处理后的数据
      .then(result => save(result)) // 接收上一步结果
      .catch(err => console.log(err)); // 统一捕获错误
    
  3. 错误冒泡
    链式调用中未处理的错误会跳过后续 .then(),直到被 .catch() 捕获:

    Promise.reject("Error")
      .then(() => console.log("不执行"))
      .catch(err => console.log(err)); // 输出 "Error"
    
  4. 微任务队列
    .then() 的回调在微任务队列执行,优先级高于宏任务(如 setTimeout):

    setTimeout(() => console.log("Macro Task"), 0);
    Promise.resolve().then(() => console.log("Micro Task"));
    // 输出顺序:Micro Task → Macro Task
    

     ⚡ 三、Promise 的静态方法

  1. 并发控制

    • Promise.all([p1, p2]):所有 Promise 成功时返回结果数组;任一失败则立即失败
    • Promise.race([p1, p2]):采用第一个完成(无论成功/失败)的结果。
    • Promise.allSettled([p1, p2])(ES2020):等待所有完成,返回状态和结果数组。
  2. 快速创建

    • Promise.resolve(value):创建立即成功的 Promise。
    • Promise.reject(error):创建立即失败的 Promise。

     ⚠️ 四、常见问题与最佳实践

  1. 典型错误

    • .then() 不执行:检查是否遗漏 resolve/reject 调用。
    • 未处理拒绝:未用 .catch() 捕获错误可能导致程序崩溃。
    • 循环中的误用:在循环内直接 await 会导致顺序执行,应用 Promise.all 并行化:
      // 错误:顺序执行
      for (const item of list) await process(item);
      
      // 正确:并行执行
      await Promise.all(list.map(item => process(item)))
  2. 最佳实践

    • 始终处理错误:链式调用末尾添加 .catch() 或使用 try/catch(配合 async/await)。
    • 避免嵌套:用链式调用替代回调嵌套。
    • 并行优化:独立异步操作用 Promise.all() 提升性能。

     💎 总结

特性说明
状态管理三种不可逆状态(Pending → Fulfilled/Rejected)
链式调用.then() 返回新 Promise,解决回调地狱问题
错误处理通过 .catch() 或链末错误冒泡统一捕获
并发控制Promise.all()/Promise.race() 实现多任务协作

掌握 Promise 和 .then() 是高效处理异步操作的基础。建议结合 async/await 提升可读性,复杂场景搭配 Promise.all() 优化性能。

















🤔 参考 20

以下是 JavaScript 中 Promise.then() 的深度解析,通过「场景化示例」帮助您彻底理解异步控制流:


一、Promise 核心机制
     场景:模拟用户登录流程

// 创建 Promise 对象
const login = (username, password) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (username === 'admin' && password === '123456') {
        resolve({ id: 1, name: '管理员' }) // 登录成功
      } else {
        reject(new Error('认证失败')) // 登录失败
      }
    }, 1000);
  });
};

     生命周期三状态:

  1. Pending(等待态)setTimeout 计时期间
  2. Fulfilled(完成态):调用 resolve()
  3. Rejected(拒绝态):调用 reject()

二、 .then() 链式工作流
     场景:登录成功后获取用户订单

login('admin', '123456')
  .then(user => {
    console.log('登录用户:', user.name)
    return fetchOrders(user.id) // 返回新Promise
  })
  .then(orders => {
    console.log('获得订单:', orders)
    return processOrders(orders) 
  })
  .then(result => {
    console.log('订单处理结果:', result)
  })
  .catch(error => {
    console.error('流程异常:', error.message)
  });

     链式调用特点:

  • 每次 .then() 返回新 Promise 对象
  • 前一个 .then() 的返回值会成为下一个 .then() 的参数
  • 错误会冒泡传递直到被 .catch() 捕获

三、高阶技巧演示
     1. 处理嵌套异步

// 传统回调地狱 vs Promise 解决方案
getUser(userId)
  .then(user => getProfile(user.profileId))
  .then(profile => getOrders(profile.orderHistoryId))
  .then(orders => renderOrders(orders));

     2. 并行处理多个 Promise

const loadDashboard = () => {
  return Promise.all([
    fetchUserData(),
    fetchProductList(),
    fetchLatestNews()
  ]).then(([user, products, news]) => {
    return { user, products, news }
  });
}

     3. 错误处理策略对比

// 方式1:每个 then 单独处理
promise
  .then(
    result => { /* 成功处理 */ },
    error => { /* 当前阶段错误处理 */ }
  )

// 方式2:统一错误捕获 (推荐)
promise
  .then(step1)
  .then(step2)
  .catch(handleAllErrors) // 捕获链中所有错误

四、Promise 原理解剖
     1. 基础结构伪代码

class MyPromise {
  constructor(executor) {
    this.state = 'pending'
    this.value = undefined
    
    const resolve = (value) => {
      if (this.state === 'pending') {
        this.state = 'fulfilled'
        this.value = value
        // 触发 then 注册的回调
      }
    }
    
    const reject = (reason) => {
      if (this.state === 'pending') {
        this.state = 'rejected'
        this.value = reason
        // 触发 catch 注册的回调
      }
    }
    
    try {
      executor(resolve, reject)
    } catch (err) {
      reject(err)
    }
  }

  then(onFulfilled, onRejected) { /* ... */ }
}

     2. 微任务队列机制

  • Promise 回调会被放入微任务队列
  • 执行优先级高于 setTimeout 等宏任务
console.log('开始')

Promise.resolve()
  .then(() => console.log('微任务1'))

setTimeout(() => console.log('宏任务'), 0)

Promise.resolve()
  .then(() => console.log('微任务2'))

console.log('结束')

/* 输出顺序:
开始
结束
微任务1
微任务2
宏任务 */

五、开发常见误区
     1. Promise 吞没错误

// ❌ 危险:未处理的拒绝
new Promise((_, reject) => reject('错误'))
  .then(() => console.log('永远不会执行'))

// ✅ 正确做法
.catch(error => console.error('捕获错误:', error))

     2. 断开的 Promise 链

// ❌ 错误:忘记 return
getUser()
  .then(user => {
    updateProfile(user) // 没有返回 Promise
  })
  .then(result => {
    // result 会是 undefined
  })

// ✅ 正确:确保返回
  .then(user => {
    return updateProfile(user) // 显式返回
  })

     3. 不必要的嵌套

// ❌ 过度嵌套
checkAuth()
  .then(token => {
    getUser(token).then(user => {
      getOrders(user.id).then(orders => {
        // ...
      })
    })
  })

// ✅ 扁平化处理
checkAuth()
  .then(token => getUser(token))
  .then(user => getOrders(user.id))
  .then(orders => { /* ... */ })

六、最佳实践指南

  1. 始终返回结果:每个 .then() 中 return 值或新 Promise
  2. 优先使用 catch:统一错误处理比分散更可靠
  3. 命名 Promise 链:便于调试追踪
    const authPromise = login()
      .then(handleAuth)
      .catch(handleAuthError)
    
    authPromise.then(/* ... */)
    
  4. Promise 化回调函数
    const readFilePromise = (filename) => {
      return new Promise((resolve, reject) => {
        fs.readFile(filename, (err, data) => {
          err ? reject(err) : resolve(data)
        })
      })
    }
    

掌握这些核心要点后,您将能够:

  • 轻松处理网络请求、定时操作等异步任务
  • 编写可维护性更高的异步代码
  • 避免常见的 Promise 陷阱
  • 为后续学习 async/await 打下坚实基础



























JavaScript Promise 中 then() 的第二个参数 vs catch() 方法详解

在 JavaScript 的 Promise 中,then() 方法的第二个参数和 catch() 方法都用于处理 Promise 的拒绝状态,但它们在错误处理机制上存在重要区别。下面我将深入解析两者的差异和使用场景。

核心概念对比

特性then(, onRejected)catch(onRejected)
语法位置then() 的第二个参数独立的链式方法
错误捕获范围仅捕获前一个 Promise 的拒绝捕获链中前面所有未处理的拒绝
链式影响处理错误后返回 resolved Promise处理错误后返回 resolved Promise
处理自身错误❌ 不能捕获自身回调中的错误✅ 可以捕获前面所有回调中的错误
推荐使用场景特定步骤的错误恢复全局错误处理

详细解析

     1. then() 的第二个参数:精确错误处理

promise
  .then(
    onFulfilled, 
    onRejected // 第二个参数
  )

特点:

  • 只处理直接前驱 Promise 的拒绝状态
  • 无法处理同一个 then()onFulfilled 回调抛出的错误
  • 适合处理特定步骤的预期错误

示例:

const specificHandler = new Promise((resolve, reject) => {
  reject("步骤1失败");
});

specificHandler
  .then(
    result => console.log("成功:", result),
    error => {
      console.log("处理步骤1错误:", error);
      return "使用备用方案"; // 返回新值继续链式调用
    }
  )
  .then(result => console.log("后续步骤:", result));

// 输出:
// 处理步骤1错误: 步骤1失败
// 后续步骤: 使用备用方案

     2. catch() 方法:全局错误处理

promise
  .then(onFulfilled)
  .catch(onRejected) // 捕获链中所有错误

特点:

  • 捕获前面整个链中未处理的拒绝状态
  • 可以处理前面任何 then() 回调中抛出的错误
  • then(undefined, onRejected) 的语法糖
  • 适合作为全局错误处理器

示例:

const globalHandler = new Promise(resolve => resolve("初始数据"));

globalHandler
  .then(result => {
    console.log("步骤1:", result);
    throw new Error("步骤2失败"); // 在回调中抛出错误
  })
  .then(result => console.log("这个回调不会执行"))
  .catch(error => {
    console.log("捕获所有错误:", error.message);
    return "错误恢复";
  })
  .then(result => console.log("恢复后继续:", result));

// 输出:
// 步骤1: 初始数据
// 捕获所有错误: 步骤2失败
// 恢复后继续: 错误恢复

关键区别详解

     1. 错误捕获范围不同

new Promise((_, reject) => reject("初始失败"))
  .then(
    () => {}, 
    err => console.log("then捕获:", err) // 捕获初始拒绝
  )
  .then(() => {
    throw new Error("后续错误");
  })
  .catch(err => console.log("catch捕获:", err)); // 捕获后续错误

     2. 处理链中回调错误的能力

// then() 第二个参数无法捕获自身回调中的错误
new Promise(resolve => resolve("成功"))
  .then(
    () => {
      throw new Error("回调错误");
    },
    err => console.log("这个处理器不会执行") // ❌ 无法捕获
  )
  .catch(err => console.log("catch捕获:", err)); // ✅ 可以捕获

// 输出: catch捕获: Error: 回调错误

     3. 组合使用的推荐模式

fetchData()
  .then(handleData, handleSpecificError) // 处理特定错误
  .then(processData)
  .catch(handleGlobalError); // 全局错误兜底

使用场景建议

     使用 then() 第二个参数当:

  1. 需要为特定操作提供错误恢复
  2. 某些错误是预期内且可恢复的
  3. 需要为不同步骤提供不同的错误处理
paymentService
  .processPayment(order)
  .then(
    receipt => saveReceipt(receipt),
    paymentError => {
      if (paymentError.code === "INSUFFICIENT_FUNDS") {
        return retryWithAlternativePayment(order); // 特定恢复
      }
      throw paymentError; // 重新抛出其他错误
    }
  )
  .catch(handleUnexpectedErrors); // 全局处理

     使用 catch() 当:

  1. 需要全局错误处理
  2. 处理意外不可恢复的错误
  3. 需要简化错误处理逻辑
  4. 作为 Promise 链的最终兜底
userAuth
  .login(credentials)
  .then(fetchUserProfile)
  .then(loadUserPreferences)
  .then(initializeApp)
  .catch(error => {
    console.error("认证流程失败:", error);
    showLoginError();
    return null;
  });

高级错误处理模式

     1. 错误分类处理

api.getData()
  .then(data => transformData(data))
  .catch(error => {
    if (error instanceof NetworkError) {
      return cachedData(); // 网络错误恢复
    } else if (error instanceof ValidationError) {
      return defaultData(); // 验证错误恢复
    }
    throw error; // 重新抛出未知错误
  })
  .catch(handleCriticalErrors); // 处理未知错误

     2. 错误重试机制

function fetchWithRetry(url, retries = 3) {
  return fetch(url)
    .catch(error => {
      if (retries > 0) {
        console.log(`重试剩余次数: ${retries}`);
        return fetchWithRetry(url, retries - 1);
      }
      throw error; // 重试耗尽后抛出
    });
}

fetchWithRetry("https://api.example.com/data")
  .then(handleData)
  .catch(handleFinalError);

     3. 并行操作错误处理

Promise.all([
  fetchUser(),
  fetchPosts(),
  fetchComments()
])
  .then(([user, posts, comments]) => {
    // 处理所有数据
  })
  .catch(error => {
    if (error.errors) {
      // 处理多个错误(使用Promise.allSettled时)
      error.errors.forEach(err => console.error("部分失败:", err));
    } else {
      console.error("全局失败:", error);
    }
  });

最佳实践总结

  1. 优先使用 catch():作为全局错误处理器更安全
  2. 特定恢复用 then(, onRejected):当需要精确处理特定错误时
  3. 总是返回或抛出:在错误处理程序中明确控制流程
  4. 避免混合风格:在链中统一使用一种错误处理方式
  5. 使用错误类型检查:用 instanceof 区分不同错误
  6. 不要忽略错误:即使只是记录日志也要处理
  7. 考虑 finally:用 finally() 处理清理逻辑
// 推荐的综合模式
initializeApp()
  .then(loadData, handleInitError) // 特定初始化错误
  .then(processData)
  .then(renderUI)
  .catch(handleUnexpectedError) // 全局错误捕获
  .finally(cleanupResources); // 无论成功失败都执行

理解 then() 的第二个参数和 catch() 的区别是掌握 Promise 错误处理的关键。根据具体场景选择合适的错误处理方式,可以创建更健壮、可维护的异步 JavaScript 代码。



























JavaScript异步编程: 回调callback , Promise,then,catch,finally , async,await 笔记250810







JavaScript异步,笔记250810







JavaScript的 Promise,then,catch,finally,async,await 笔记250810







JavaScript的 Promise,then 笔记250803







Js的 Promise的 then catch 笔记240222







Promise().then().catch().finally() 笔记250804







Promise的reject处理: then的第二个回调 与 catch回调 笔记250804







JavaScript的 async , await 笔记250808







Promise,then 与 async,await 相互转换 笔记250810







JavaScript的Callback回调函数转Promise().then()和async{await} 笔记250810







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kfepiza

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值