Promise的用法解析

Promise是ES6之后新增的一个重要知识点(也可以说是最重要的知识点之一),是每个前端开发都必须要掌握的知识点。
本章中我们将详细学习下Promise的各种用法

一. 认识Promise

1.1 异步回调处理

我们这里用一个实际的例子来切入:

  • 我们调用一个函数,这个函数中发送网络请求(我们可以用定时器来模拟);
  • 如果发送网络请求成功了,那么告知调用者发送成功,并且将相关数据返回过去;
  • 如果发送网络请求失败了,那么告知调用者发送失败,并且告知错误信息;

比如我们将网络请求封装到一个request.js的文件中:

// request.js
function requestData(url) {
   
   
  setTimeout(() => {
   
   
    if (url === "http://coderwhy.org") {
   
   
      // 发送成功了
      console.log("发送成功==========");
    } else {
   
   
      // 发送失败了
      console.log("发送失败==============");
    }
  }, 1000);
}

requestData("http://www.baidu.com");

我们将面临两个问题:

  • 如果我们请求成功了,如何告知调用者成功了
  • 如果我们请求失败了 ,如何告知调用则失败了

在传统的代码中我们有一种方式:回调函数

// request.js
function requestData(url, successCallback, failureCallback) {
   
   
  setTimeout(() => {
   
   
    if (url === "http://coderwhy.org") {
   
   
      // 发送成功了
      successCallback("一组数据");
    } else {
   
   
      // 发送失败了
      failureCallback("请求url错误");
    }
  }, 1000);
}

requestData(
  "http://www.baidu.com",
  (res) => {
   
   
    console.log("请求成功 :", res);
  },
  (err) => {
   
   
    console.log("请求失败:", err);
  }
);

执行结果:
在这里插入图片描述

1.2 什么是Promise

在上面的解决方案中,我们确实可以将执行通过回调函数告知调用法,但是存在链各个主要的问题:

  • 我们需要自己来设计回调函数、回调函数的名称、回调函数的使用等
  • 对于不同的人, 不同的框架设计出来的方案是不一样的,那么我们必须耐心去看别人的源码或者文档,以便可以理解它这个函数到底怎么用

我们来看一下Promise的API是怎么样的:

  • Promise是一个类,可以翻译成 承诺许诺期约
  • 当我们需要给予调用者一个承诺:待会儿我会给你回调数据时,就可以创建一个Promise的对象
  • 在通过new创建Promise对象时,我们需要传入一个回调函数,我们称之为executor
    • 这个回调函数会被立即执行,并且给传入另外两个回调函数resolvereject
    • 当我们调用resolve回调函数时,会执行Promise对象的then方法传入的回调函数
    • 当我们调用reject回调函数时,会执行Promise对象的catch方法传入的回调函数
const promise = new Promise((resolve, reject) => {
   
   
  // 调用resolve, 那么then传入的回调会被执行
  resolve("哈哈哈");
  // 调用reject, 那么catch传入的回调会被执行
  reject("错误信息");
});

promise
  .then((res) => {
   
   
    console.log(res);
  })
  .catch((err) => {
   
   
    console.log(err);
  });

上面的Promise使用过程, 我们可以将它划分为三个状态

  • 待定(Pending): 初始状态,既没有被兑现,也没有被拒绝
    • 当执行executor中的代码时,处于该状态;
  • 已兑现(fulfilled): 意味着操作成功完成
    • 执行了resolve时,处于该状态;
  • 已拒绝(rejected): 意味着操作失败
    • 执行了reject时,处于该状态

1.3 Promise重构

那么有了Promise,我们就可以将之前的代码进行重构了:

// request.js
function requestData(url) {
   
   
  return new Promise((resolve, reject) => {
   
   
    setTimeout(() => {
   
   
      if (url === "http://coderwhy.org") {
   
   
        // 发送成功了
        resolve("一组成功数据");
      } else {
   
   
        // 发送失败了
        reject("请求url错误");
      }
    }, 1000);
  });
}

// main.js
const promise = requestData("http://coderwhy.org");
promise
  .then((res) => {
   
   
    console.log(res);
  })
  .catch((err) => {
   
   
    console.log(err);
  });

执行结果:
在这里插入图片描述

二. Promise对象方法

2.1. Executor

Executor是在创建Promise时需要传入的一个回调函数,这个回调函数会被立即执行,并且传入两个参数:

new Promise((resolve, reject) => {
   
   
  console.log("executor代码")
})

通常我们会在Executor中确定我们的Promise状态:

  • 通过resolve,可以兑现(fulfilled)Promise的状态,我们也可以称之为已决议(resolved);
  • 通过reject,可以拒绝(reject)Promise的状态;

注意一旦状态被确定下来,Promise的状态会被 锁死,该Promise的状态是不可更改的

  • 在我们调用resolve的时候,如果resolve传入的值本身不是一个Promise,那么会将该Promise的状态变成 兑现(fulfilled)
  • 在之后我们去调用reject时,已经不会有任何的响应了(并不是这行代码不会执行,而是无法改变Promise状态);
const promise = new Promise((resolve, reject) => {
   
   
  // 调用resolve, 那么then传入的回调会被执行
  resolve("哈哈哈");
  // 调用reject, 那么catch传入的回调会被执行
  reject("错误信息");
});

promise
  .then((res) => {
   
   
    console.log(res);
  })
  .catch((err) => {
   
   
    console.log(err);
  });

执行结果:
在这里插入图片描述

如果resolve中传入的是另外一个Promise,那么这个新Promise会决定原Promise的状态:

new Promise((resolve, reject) => {
   
   
  resolve(new Promise((resolve
PromiseJavaScript 中处理异步操作的重要机制,它通过状态变化来管理异步任务的结果,并提供链式调用的能力,使得异步代码更易于理解和维护。 ### Promise 的基本结构 Promise 是一个对象,表示一个异步操作的最终完成(成功或失败)。创建一个 Promise 时,需要传入一个执行器函数,该函数有两个参数:`resolve` 和 `reject`,分别用于在操作成功或失败时通知 Promise 状态的改变[^3]。 ```javascript let promise = new Promise(function(resolve, reject) { // 异步操作 if (/* 操作成功 */) { resolve("操作成功"); } else { reject("操作失败"); } }); ``` ### Promise 的状态 Promise 有三种状态: - **Pending(进行中)**:初始状态,既不是成功也不是失败。 - **Fulfilled(已成功)**:操作成功完成,调用 `resolve` 后进入此状态。 - **Rejected(已失败)**:操作失败,调用 `reject` 后进入此状态。 一旦状态改变,就不会再变,这保证了 Promise 的结果是不可变的[^3]。 ### 使用 `.then()` 和 `.catch()` Promise 的消费者通过 `.then()` 和 `.catch()` 方法来注册成功和失败的回调函数。`.then()` 接收两个参数,第一个是成功回调,第二个是失败回调;`.catch()` 只处理失败的情况。 ```javascript promise .then( result => console.log("成功:" + result), error => console.log("错误:" + error) ) .catch(error => console.log("捕获错误:" + error)); ``` ### 使用 `.finally()` `.finally()` 方法用于注册一个回调,在 Promise 被解决(无论是成功还是失败)后执行,常用于清理资源或执行最终操作[^4]。 ```javascript promise .then(result => console.log("成功:" + result)) .catch(error => console.log("错误:" + error)) .finally(() => console.log("运行结束")); ``` ### 链式调用与返回值 在 `.then()` 中返回一个值,会自动被包装成一个新的 Promise,从而实现链式调用。如果返回的是另一个 Promise,则当前链的下一个 `.then()` 会等待该 Promise 的解决[^2]。 ```javascript new Promise((resolve, reject) => { setTimeout(() => resolve(1), 1000); }) .then(result => { console.log(result); // 1 return result * 2; }) .then(result => { console.log(result); // 2 return result * 2; }) .then(result => { console.log(result); // 4 }); ``` ### 错误传播 如果在链式调用中任何一步发生错误,并且没有在 `.catch()` 中处理,错误会继续向后传播,直到被捕获或导致未处理的 Promise 拒绝。 ```javascript new Promise((resolve, reject) => { throw new Error("出错了"); }) .catch(error => console.log("捕获到错误:" + error.message)) .then(() => console.log("继续执行")); ``` ### 使用 `Promise.all()` 和 `Promise.race()` - **`Promise.all(iterable)`**:等待所有 Promise 完成,如果其中任何一个被拒绝,则立即拒绝。 - **`Promise.race(iterable)`**:等待第一个 Promise 完成(无论是成功还是失败)。 ```javascript Promise.all([promise1, promise2, promise3]) .then(values => console.log(values)) .catch(error => console.log("有一个失败了:" + error)); Promise.race([promise1, promise2]) .then(value => console.log("第一个完成的是:" + value)); ``` ### 示例:定时任务 以下是一个典型的 Promise 示例,模拟一个异步定时任务: ```javascript let promise = new Promise((resolve, reject) => { setTimeout(() => { resolve("定时任务结果(resolve)"); }, 1000); }); promise .then( result => console.log("成功(then):" + result), error => console.log("错误(then):" + error) ) .finally(() => console.log("运行结束(finally)")); ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值