JS 入门通关手册(24):Promise:从回调地狱到异步优雅写法

回调函数虽然能实现异步,但一旦遇到多个有依赖的异步任务,就会变成嵌套多层的回调地狱,代码难读、难维护、难调试。

Promise 就是为了解决这个问题而生的。它不是新的异步功能,而是异步代码的管理方案,让异步代码可以像同步代码一样链式书写。


一、Promise 是什么?

一句话:Promise 是一个表示异步操作最终完成(或失败)的对象,它让你能把回调写法改成链式调用写法,彻底告别回调地狱。

它有三种状态:

  1. pending:等待中(初始状态)
  2. fulfilled:已成功(操作完成)
  3. rejected:已失败(操作出错)

特点:

  • 状态一旦改变,就凝固不变
  • 从 pending → fulfilled 或 pending → rejected
  • 改变后不可再修改

二、Promise 基本用法

1. 创建 Promise

javascript

运行

javascript 复制代码
const p = new Promise((resolve, reject) => {
  // 异步操作
  setTimeout(() => {
    // 成功
    resolve("数据拿到了");

    // 失败
    // reject("请求失败");
  }, 1000);
});

2. 使用 then 接收结果

javascript

运行

javascript 复制代码
p.then(res => {
  console.log("成功:", res);
}).catch(err => {
  console.log("失败:", err);
});

3. 封装一个异步请求(模拟接口)

javascript

运行

javascript 复制代码
function request(url) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (url) {
        resolve({ data: "用户数据", code: 200 });
      } else {
        reject("url 不能为空");
      }
    }, 1000);
  });
}

// 使用
request("/api/user")
  .then(res => console.log(res))
  .catch(err => console.log(err));

三、Promise 链式调用(核心:解决回调地狱)

这是 Promise 最强大的地方:then 可以返回新 Promise,继续 then

对比回调地狱:

javascript

运行

javascript 复制代码
// 以前回调地狱
getID(function (id) {
  getUser(id, function (user) {
    getOrder(user, function (order) {
      console.log(order);
    });
  });
});

Promise 链式写法:

javascript

运行

javascript 复制代码
request("/id")
  .then(id => request("/user/" + id))
  .then(user => request("/order/" + user.id))
  .then(order => console.log(order))
  .catch(err => console.log("出错:", err));

清爽、线性、可维护!


四、Promise 常用 API

1. Promise.then()

成功时执行,可返回新 Promise 继续链式。

2. Promise.catch()

捕获任何环节的错误。

3. Promise.finally()

无论成功失败,一定执行(常用于关闭加载)。

javascript

运行

javascript 复制代码
request("/api")
  .then(res => {})
  .catch(err => {})
  .finally(() => {
    console.log("结束");
  });

4. Promise.all()

多个请求并行,全部成功才成功

javascript

运行

javascript 复制代码
const p1 = request("/api1");
const p2 = request("/api2");

Promise.all([p1, p2])
  .then(res => console.log(res[0], res[1]))
  .catch(err => console.log("有一个失败就失败"));

5. Promise.race()

谁先完成就用谁(不管成功失败)。

javascript

运行

javascript 复制代码
Promise.race([p1, p2]).then(res => console.log("最快的结果"));

6. Promise.resolve() / Promise.reject()

快速返回成功 / 失败的 Promise。

javascript

运行

javascript 复制代码
Promise.resolve(123).then(res => console.log(res));

五、Promise 手写小案例(模拟真实接口)

javascript

运行

javascript 复制代码
// 模拟获取用户ID
function getUserId() {
  return new Promise(resolve => {
    setTimeout(() => resolve(1001), 1000);
  });
}

// 模拟获取用户信息
function getUserInfo(id) {
  return new Promise(resolve => {
    setTimeout(() => resolve({ id, name: "张三" }), 1000);
  });
}

// 模拟获取订单
function getOrder(user) {
  return new Promise(resolve => {
    setTimeout(() => resolve({ orderId: 1, userId: user.id }), 1000);
  });
}

// 链式调用(完全没有嵌套)
getUserId()
  .then(id => getUserInfo(id))
  .then(user => getOrder(user))
  .then(order => console.log("最终订单:", order));

六、常见面试题

1. Promise 有哪几种状态?

pending、fulfilled、rejected。

2. Promise 解决了什么问题?

回调地狱,让异步代码可链式、可阅读、可维护。

3. then、catch、finally 的执行顺序?

  • 成功:then → finally
  • 失败:catch → finally
  • finally 一定执行

4. Promise.all 和 Promise.race 区别?

  • all:全部成功才成功
  • race:谁快返回谁

5. Promise 是异步还是同步?

Promise 本身是同步执行 的,then/catch/finally 是微任务异步


七、总结

  1. Promise 是异步封装对象,解决回调地狱
  2. 状态:pending → fulfilled /rejected
  3. 核心写法:new Promise((resolve,reject)=>{})
  4. 链式:.then().catch().finally()
  5. 并行:Promise.all()Promise.race()

Promise 是现代 JS 异步的基石,下一篇我们学习 async/await ------ Promise 的语法糖,让异步代码写得和同步一模一样

相关推荐
吴声子夜歌15 小时前
ES6——Symbol详解
开发语言·javascript·es6
han_hanker16 小时前
js 加减乘除精度问题2
开发语言·javascript·ecmascript
ldybk16 小时前
教学vue
前端·javascript·vue.js
卷卷说风控16 小时前
工作流的 Skill 怎么写?
java·javascript·人工智能·chrome·安全
还是大剑师兰特16 小时前
Pinia介绍及Vue3配置示例
前端·javascript·vue.js
还是大剑师兰特16 小时前
Vue3 Mixin 与 Vue2 Mixin 核心区别
前端·javascript·vue.js
188号安全攻城狮16 小时前
【前端基础知识】JavaScript 数组方法总结:从表格速查到分类详解
开发语言·前端·javascript·网络安全
英俊潇洒美少年16 小时前
迷你 React 调度器(带优先级+时间切片)手写实现
前端·javascript·react.js
freeWayWalker17 小时前
Vue通用缩放容器
前端·javascript·vue.js
Hello--_--World17 小时前
VUE:逻辑复用
前端·javascript·vue.js