Promise学习

embedded/2024/10/19 9:40:46/

理论知识

前端开发中,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,就拒绝这个 Promisereject('请求失败,状态码:' + 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-ignorewindow.SDK360.init({ ...});// @ts-ignorewindow.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.ppmy.cn/embedded/105574.html

相关文章

python dict转json字符串后写入csv后去除多余的引号

问题描述 dict转为标准json格式化字符串json_str&#xff0c;再把这个json字符串使用csv库写入csv文件 会有多余的双引号。 伪代码如下&#xff1a; import os import re import cv2 import glob import csv import json from tqdm import tqdmwith open(test.csv, w, newline…

Git学习尚硅谷(003 git分支操作)

尚硅谷Git入门到精通全套教程&#xff08;涵盖GitHub\Gitee码云\GitLab&#xff09; 总时长 4:52:00 共45P 此文章包含第15p-第p18的内容 文章目录 git分支操作分支介绍分支的好处 分支的操作查看分支创建分支切换分支&修改分支合并分支正常合并分支冲突合并 git分支操作…

QT_ERROR running qmake

文章目录 之前一直以为没有对应的msvc版本。。。。 尝试过网上的其他解答&#xff0c;将qt插件的版本和属性的版本统一没用

基于微信小程序儿童预防接种预约小程序

博主介绍&#xff1a; 大家好&#xff0c;本人精通Java、Python、C#、C、C编程语言&#xff0c;同时也熟练掌握微信小程序、Php和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我有丰富的成品Java、Python、C#毕设项目经验&#xff0c;能够为学生提供各类…

基于深度学习的人机交互中的认知模型

基于深度学习的人机交互中的认知模型旨在使计算机系统能够更好地理解、预测和响应人类行为和意图&#xff0c;从而实现更自然和有效的交互体验。这类认知模型综合了深度学习技术和认知科学的原理&#xff0c;以模拟人类的感知、思维、情感和决策过程。 1. 基于深度学习的认知模…

裁剪视频如何让画质不变?小白都在用这些

怎么裁剪视频画面&#xff1f;其实&#xff0c;它已经成为许多人日常生活中的一项基本技能。 无论是制作温馨的家庭视频、分享日常点滴&#xff0c;还是进行专业的视频剪辑&#xff0c;裁剪视频都是一个关键步骤。 本文将为你详细介绍4个简单易学的视频裁剪教程&#xff0c;让…

基于约束大于规范的想法,封装缓存组件

架构&#xff1f;何谓架构&#xff1f;好像并没有一个准确的概念。以前我觉得架构就是搭出一套完美的框架&#xff0c;可以让其他开发人员减少不必要的代码开发量&#xff1b;可以完美地实现高内聚低耦合的准则;可以尽可能地实现用最少的硬件资源&#xff0c;实现最高的程序效率…

贪心算法---划分字母区间

题目&#xff1a; 给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段&#xff0c;同一字母最多出现在一个片段中。 注意&#xff0c;划分结果需要满足&#xff1a;将所有划分结果按顺序连接&#xff0c;得到的字符串仍然是 s 。 返回一个表示每个字符串片段的长度…