当前位置: 首页 > article >正文

Promise学习

理论知识

在前端开发中,Promise 是 JavaScript 中用于处理异步操作的一种方式。它提供了一种更直观和简洁的方式来处理异步任务,避免了传统回调函数中“回调地狱”的问题。以下是关于 Promise 的详细解释和代码示例。

什么是 Promise?

Promise 确实可以被看作是异步操作的返回结果

Promise 是一个代表异步操作最终完成或失败的对象。它可以用来处理异步操作的结果(成功或失败)并执行相应的操作。

它会在异步操作完成后,通过 resolve 或 reject 返回结果。这个结果可以是操作成功的值,也可以是操作失败的原因。通过使用 then、catch 和 finally 等方法,你可以定义当异步操作完成后该执行的操作。

const promise = new Promise((resolve, reject) => {
  // 一些异步操作,比如数据请求
  const success = true;

  if (success) {
    resolve("操作成功!");
  } else {
    reject("操作失败!");
  }
});

在这个例子中,Promise 构造函数接受一个执行器函数(executor),该函数带有两个参数:resolverejectresolve 用于异步操作成功时返回结果,reject 用于异步操作失败时返回错误。

Promise 的状态

一个 Promise 对象有三种状态:

  1. Pending(待定): 初始状态,既没有被解决也没有被拒绝。
  2. Fulfilled(已解决): 操作成功完成,Promise 被解决,resolve 被调用。
  3. Rejected(已拒绝): 操作失败,Promise 被拒绝,reject 被调用。

状态一旦从 Pending 变为 FulfilledRejected,就不能再更改

resolve 和 reject

resolve 用于异步操作成功时返回结果,reject 用于异步操作失败时返回错误。也就在resolve 里面传递的参数就是异步操作成功后返回的结果

  • resolve:当异步操作成功时,resolve 函数会被调用,并且可以接收一个参数,这个参数就是异步操作成功后的结果。调用 resolve 会将 Promise 的状态从“进行中(pending)”变为“已解决(fulfilled)”,并将 resolve 传入的值作为结果返回给 .then() 方法。

  • reject:当异步操作失败时,reject 函数会被调用,并且可以接收一个参数,这个参数通常是一个错误信息或对象。调用 reject 会将 Promise 的状态从“进行中(pending)”变为“已拒绝(rejected)”,并将 reject 传入的值作为错误信息返回给 .catch() 方法。

示例

const myPromise = new Promise((resolve, reject) => {
  const success = true; // 假设这个变量决定操作是否成功

  if (success) {
    resolve('操作成功!'); // 成功时调用 resolve,并传入结果
  } else {
    reject('操作失败!'); // 失败时调用 reject,并传入错误信息
  }
});

myPromise
  .then(result => {
    console.log(result); // 输出 "操作成功!"
  })
  .catch(error => {
    console.error(error); // 如果失败,会输出错误信息
  });

在这个例子中:

  • 如果 successtrueresolve('操作成功!') 会被调用,Promise 状态变为“已解决”,并将 '操作成功!' 作为结果传递给 .then()
  • 如果 successfalsereject('操作失败!') 会被调用,Promise 状态变为“已拒绝”,并将 '操作失败!' 作为错误信息传递给 .catch()

因此,resolvereject 就是用来分别处理异步操作的成功和失败结果的。

Promise 的方法

Promise 提供了一些方法来处理异步操作的结果和错误:

  1. then()

    • 用于处理 Promise 成功的情况。
    • 它接受两个回调函数,第一个用于处理 resolve 的结果,第二个用于处理 reject 的错误(可选)。
    promise.then(result => {
      console.log(result); // 操作成功!
    }, error => {
      console.error(error); // 不会执行,因为操作成功了
    });
    

then 方法可以链式调用,这意味着每个 then 都可以返回一个新的 Promise 或数据,供下一个 then 处理。catch 方法用于捕获任何可能的错误

  1. catch()

    • 用于处理 Promise 失败的情况,相当于 then 的第二个参数。
    promise.catch(error => {
      console.error(error); // 操作失败!
    });
    
  2. finally()

    • 无论 Promise 成功还是失败,都会执行 finally 中的回调函数。
    promise.finally(() => {
      console.log("操作完成,无论成功与否"); // 一定会执行
    });
    
  3. Promise.all()

    • 接受一个 Promise 对象的数组,等待所有 Promise 都解决后或有一个 Promise 被拒绝时才继续。
    const promise1 = Promise.resolve(1);
    const promise2 = Promise.resolve(2);
    const promise3 = Promise.resolve(3);
    
    Promise.all([promise1, promise2, promise3]).then(values => {
      console.log(values); // [1, 2, 3]
    });
    
  4. Promise.race()

    • 接受一个 Promise 对象的数组,一旦有一个 Promise 被解决或拒绝,立即继续。
    const promise1 = new Promise(resolve => setTimeout(resolve, 500, "One"));
    const promise2 = new Promise(resolve => setTimeout(resolve, 100, "Two"));
    
    Promise.race([promise1, promise2]).then(value => {
      console.log(value); // Two
    });
    
  5. Promise.allSettled()

    • 接受一个 Promise 对象的数组,等待所有 Promise 都解决或拒绝后才继续。
    const promise1 = Promise.resolve("成功");
    const promise2 = Promise.reject("失败");
    
    Promise.allSettled([promise1, promise2]).then(results => {
      console.log(results);
      // [{status: "fulfilled", value: "成功"}, {status: "rejected", reason: "失败"}]
    });
    
  6. Promise.any()

    • 接受一个 Promise 对象的数组,只要有一个 Promise 被解决,就继续,只有在所有 Promise 都被拒绝时才会失败。
    const promise1 = Promise.reject("失败");
    const promise2 = Promise.resolve("成功");
    
    Promise.any([promise1, promise2]).then(result => {
      console.log(result); // 成功
    }).catch(error => {
      console.error(error);
    });
    

总结

Promise 是一种强大的工具,用于简化异步操作的处理。它的三种状态和多种方法使得开发者可以灵活地管理异步操作的成功和失败情况,在实际开发中广泛应用。

具体案例

好,我们可以通过 fetch API 来模拟向 https://www.baidu.com/ 这个接口发起请求,并使用 Promise 处理响应数据。虽然 https://www.baidu.com/ 实际上并不允许跨域请求,我们可以假设这个请求是成功的,并展示如何处理请求的结果。

示例代码

function fetchBaiduData() {
  return new Promise((resolve, reject) => {
    fetch('https://www.baidu.com/')
      .then(response => {
        if (!response.ok) {
          // 如果响应状态码不是 2xx,就拒绝这个 Promise
          reject('请求失败,状态码:' + response.status);
        } else {
          // 否则,解析响应体为文本
          return response.text();
        }
      })
      .then(data => {
        resolve(data); // 请求成功,返回解析后的数据
      })
      .catch(error => {
        reject('请求失败,错误信息:' + error); // 捕获 fetch 过程中的任何错误
      });
  });
}

// 使用 Promise 处理请求结果
fetchBaiduData()
  .then(data => {
    console.log('请求成功,获取到的数据:', data);
  })
  .catch(error => {
    console.error('请求失败:', error);
  })
  .finally(() => {
    console.log('请求完成,无论成功或失败都会执行');
  });

代码解释

  1. 创建 Promise:

    • fetchBaiduData 函数中,我们使用 fetch API 向 https://www.baidu.com/ 发起请求。
    • fetch 本身返回一个 Promise,我们使用 .then 方法处理响应。
  2. 处理响应:

    • 如果响应的状态码不在 200-299 范围内,我们会通过 reject 方法拒绝这个 Promise,并传入错误信息。
    • 如果请求成功,我们通过 response.text() 方法将响应体解析为文本(也可以使用 response.json() 方法解析为 JSON 格式,视情况而定)。
  3. 链式处理:

    • 如果解析成功,调用 resolve 将解析后的数据传递给下一个 then 处理。
    • 如果在请求或解析过程中出现错误,则捕获到 catch 中,并通过 reject 返回错误信息。
  4. 使用 Promise:

    • 我们调用 fetchBaiduData 函数,并通过 then 方法处理成功的请求结果,打印数据到控制台。
    • 如果请求失败,catch 方法会捕获错误并输出错误信息。
    • 无论请求成功或失败,finally 方法都会执行,用于执行收尾操作。

在项目中的应用

笔灵web,360联运,支付功能接入

export function getPayQrcode360(params: QRCodeParams): Promise<ShutuResponse<any>> {
	return new Promise((resolve, reject) => {
		request
			.post<
				QRCodeParams,
				ShutuResponse<{
					app_id: string;
					app_secret?: string;
					...
				}>
			>(`${prefix.shutu}/pay/san60-pay-vip-build`, params)
			.then(({ code, data }) => {
				// resolve(data);
				const { app_id: appid, qid } = data;
				// @ts-ignore
				window.SDK360.init({ ...});
				// @ts-ignore
				window.SDK360.createOrder(
					{
						order_id: data.out_trade_no,
						...
					},
					(res: any) => {
						if (res.errno === 0) {
							resolve({ code, data: { ...res.data,..., out_trade_no: data.out_trade_no }, msg: '' });
						} else {
							reject({ code: 101, msg: res.errmsg });
						}
					},
					(res: any) => {
						console.log(res);
					},
				);
			});
	});
}

注意这里返回的也是Promise对象

import request from '@/utils/fetch';

export const getPayVipPolymerizePriceList = async () => {
	return request.get<any, Sh。。。onse<PriceList>>(${prefix.shutu}/pay/pay-vip。。。price-list);
};

因为request.get是用axios 创建的请求实例,axios 是一个非常流行的 HTTP 客户端,它本身的请求方法(如 get, post 等)都是异步的,并返回 Promise 对象。


http://www.kler.cn/a/284661.html

相关文章:

  • netmap.js:基于浏览器的网络发现工具
  • Spring Cloud Gateway(分发请求)
  • 用MVVM设计模式提升WPF开发体验:分层架构与绑定实例解析
  • Linux源码阅读笔记-V4L2框架基础介绍
  • 2024 年 Apifox 和 Postman 对比介绍详细版
  • 【ACM出版】第四届信号处理与通信技术国际学术会议(SPCT 2024)
  • k8s-pod 实战六 (如何在不同的部署环境中调整startupprobe的参数?)
  • [QCTF2018]X-man-A face1
  • 基于STM32的智能物料运载小车:OpenMV和OpenCV结合图像识别与运动控制算法优化(代码示例)
  • Linux和Unix的区别及为什么鸿蒙系统不用Unix的原因
  • 安卓中synchronized 关键字 的作用和介绍
  • java篇 常用工具类 0x05:基本类型的自动装箱拆箱
  • 通过Amazon Bedrock上的Stability AI模型开发生成式AI应用(上篇)
  • MySQL——基础操作
  • 证书学习(三).p12证书颁发的5个步骤、如何在线生成证书、证书工具网站推荐
  • 设计模式 14 命令模式
  • 算法训练营|图论第二天 99.岛屿数量 100.岛屿的最大面积
  • 1999-2023年上市公司年报文本数据(PDF+TXT)
  • 一文解决CLion控制台(cmd)问题【超详细】
  • SQL SUM() 函数
  • Mac环境下Python3虚拟环境创建、Flask安装以及创建运行第一个最小的Flask项目
  • k8s-pod 实战五 (Startup Probe 详细分析)
  • YoloV8实战:使用YoloV8实现OBB框检测
  • C++(Qt)-GIS开发-QGraphicsView显示瓦片地图简单示例2
  • hadoop技术
  • mmitmproxy 抓包工具使用