JS异步进化与Promise

server/2024/11/29 9:37:55/

JavaScript 是单线程的,但它并不是无法处理异步操作。相反,JavaScript 的单线程特性和其事件循环机制使得它在处理异步任务方面非常高效

回调函数(Callback Functions)

一开始JS使用回调的形式来处理异步的结果,但是异步的弊端很大

例如:无法更好的处理错误,无法追溯数据来源,无法使用同步,回调地狱等问题

javascript">console.log("开始");setTimeout(() => {console.log("异步操作完成");
}, 1000);console.log("结束");//result开始
结束
异步操作完成

回调地狱是最头疼的,所以就需要改变他

javascript">setTimeout(() => {console.log("第一步完成");setTimeout(() => {console.log("第二步完成");setTimeout(() => {console.log("第三步完成");}, 1000);}, 1000);
}, 1000);

Promise(Promise A+ 规范)

所谓Promise 就是一个承诺

Promise的状态

  • Pending(待定): 初始状态,既不是成功也不是失败
  • resolved / fullfilled (已完成): 表示操作成功完成
  • Rejected(已失败): 表示操作失败
javascript">//初始状态
let promise = new Promise((resolve, reject) => {// promise 初始状态是 pending
});//Fulfilled
let promise = new Promise((resolve, reject) => {resolve('成功的结果');
});promise.then((value) => {console.log(value); // 输出: 成功的结果
});//Rejected
let promise = new Promise((resolve, reject) => {reject('失败的原因');
});promise.catch((reason) => {console.log(reason); // 输出: 失败的原因
});

切记你从一个状态改变到另一个状态后就无法再改变了

Promise的存储

Promise 的状态可以从 pending 变为 fulfilledrejected,但一旦变为 fulfilledrejected,就不能再变为其他状态。这种状态的不可变性确保了 Promise 的一致性和可靠性,每一种状态都会有定义的返回的值

当执行函数调用 resolve 时,Promise 的状态从 pending 变为 fulfilled

resolve 可以接受一个参数,作为 Promise 成功的值, PromiseResult变为存储的数据 , 调用then的第一个回调函数来返回数据

javascript">let promise = new Promise((resolve, reject) => {setTimeout(() => {resolve('成功的结果');}, 1000);
});promise.then((value) => {console.log(value); // 1秒后输出: 成功的结果
});

当执行函数调用 reject 时,Promise 的状态从 pending 变为 rejected

reject 可以接受一个参数,作为 Promise 失败的原因, PromiseResult变为存储的数据 或 异常对象

javascript">let promise = new Promise((resolve, reject) => {setTimeout(() => {reject('失败的原因');}, 1000);
});promise.catch((reason) => {console.log(reason); // 1秒后输出: 失败的原因
});

Promise实例方法

.then

  • 用于指定当 Promise 成功时的回调函数
  • 它接受两个参数,第一个是成功时的回调函数onFulfilled
  • 第二个是失败时的回调函数onRejected(可选)
  • 返回一个新的 Promise 对象
javascript">const p1 = new Promise((resolve, reject) => {resolve("成功!");// 或// reject(new Error("错误!"));
});p1.then((value) => {console.log(value); // 成功!},(reason) => {console.error(reason); // 错误! //但是这个回调不常用,建议使用.catch},
);

.catch

  • 用于指定当 Promise 失败时的回调函数onRejected
  • 抛出错误也可以使状态变为Rejected
  • Promise已对现,则catch不会被调用
  • 返回一个新的 Promise 对象
javascript">let promise = new Promise((resolve, reject) => {reject('失败');
});promise.catch(function(reason) {console.log(reason); // 失败
});

.finally

  • 用于指定不论 Promise 最终状态如何都会执行的回调函数
  • 返回一个新的 Promise 对象
javascript">function checkMail() {return new Promise((resolve, reject) => {if (Math.random() > 0.5) {resolve('Mail has arrived');} else {reject(new Error('Failed to arrive'));}});
}checkMail().then((mail) => {console.log(mail);}).catch((err) => {console.error(err);}).finally(() => {console.log('Experiment completed');});

 Promise静态方法

.resolve

  • 返回一个成功的以给定值解析后的 Promise 对象
  • 如果传入的参数是一个 Promise 对象,则参数的结果直接影响返回值
  • 如果不是Promise 对象,那么就直接返会成功的Promise 对象
  • 该函数将嵌套的类 Promise 对象(例如,一个将被兑现为另一个 Promise 对象的 Promise 对象)展平,转化为单个 Promise 对象,其兑现值为一个非 thenable
javascript">Promise.resolve(42).then(function(value) {console.log(value); // 42 //resolve
});let p1 = Promise.resolve(521);
console.log(p1)  //resolve

.reject

  • 返回一个失败的 Promise
  • 无论参数的形式,结果都是失败的,哪怕是成功的Promise
javascript">function resolved(result) {console.log('Resolved');
}function rejected(result) {console.error(result);
}Promise.reject(new Error('fail')).then(resolved, rejected);
// Expected output: Error: fail

.all

  • 接受一个包含多个 Promise 的数组,返回的也是数组
  • 返回一个新的 Promise, 当所有传入的 Promise 都成功完成(fulfilled)时完成
  • 或者只要有一个 Promise 失败(rejected)时就失败并带有第一个被拒绝的原因
javascript">const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {setTimeout(resolve, 100, 'foo');
});Promise.all([promise1, promise2, promise3]).then((values) => {console.log(values);
});
// Expected output: Array [3, 42, "foo"]

.race

  • 接受一个包含多个 Promise 的数组
  • 返回一个新的 Promise,谁先执行完毕,谁的结果就决定race的结果
javascript">const promise1 = new Promise((resolve, reject) => {setTimeout(resolve, 500, 'one');
});const promise2 = new Promise((resolve, reject) => {setTimeout(resolve, 100, 'two');
});Promise.race([promise1, promise2]).then((value) => {console.log(value);// Both resolve, but promise2 is faster
});
// Expected output: "two"

.any

  • 接受一个可迭代对象
  • 返回一个新的 Promise只要传入的 Promise 中有一个成功,并返回第一个兑现的值
  • 如果所有的 Promise 都失败,则返回一个失败的 Promise,并附带一AggregateError 错误
javascript">const promise1 = Promise.reject(0);
const promise2 = new Promise((resolve) => setTimeout(resolve, 100, 'quick'));
const promise3 = new Promise((resolve) => setTimeout(resolve, 500, 'slow'));const promises = [promise1, promise2, promise3];Promise.any(promises).then((value) => console.log(value));// Expected output: "quick"

关于Promise的详细内容还有许多,本文仅做简略描述,请谅解

async与await (ES8/ES2017)

他的作用就是使你的promise代码看起来像同步一样

async

  • 用于声明一个异步函数
  • 异步函数默认返回一个 Promise 对象
  • 如果函数内部返回的是一个非 Promise 的值,它会被自动封装成 Promise.resolve(value)

await 

  • 用于等待一个异步操作(即 Promise)的完成
  • await 必须在 async 函数内部使用
  • 它会暂停代码执行,直到 Promise 的结果返回(成功或失败)

 传统写法

javascript">function fetchData() {return new Promise((resolve) => {setTimeout(() => resolve("数据加载完成"), 1000);});
}fetchData().then((result) => {console.log(result);return "下一步操作";}).then((nextResult) => {console.log(nextResult);}).catch((err) => {console.error(err);});

新式写法

javascript">async function fetchData() {return new Promise((resolve) => {setTimeout(() => resolve("数据加载完成"), 1000);});
}async function run() {try {const result = await fetchData();console.log(result);const nextResult = "下一步操作";console.log(nextResult);} catch (err) {console.error(err);}
}run();


http://www.ppmy.cn/server/145872.html

相关文章

【Linux】剧幕中的灵魂更迭:探索Shell下的程序替换

🎬 个人主页:谁在夜里看海. 📖 个人专栏:《C系列》《Linux系列》《算法系列》 ⛰️ 一念既出,万山无阻 目录 📖一、进程程序替换 1.替换的演示 ❓替换与执行流 ❓程序替换≠进程替换 2.替换的原理 …

Java 反射(Reflection)

Java 反射(Reflection) Java 反射(Reflection)是一个强大的特性,它允许程序在运行时查询、访问和修改类、接口、字段和方法的信息。反射提供了一种动态地操作类的能力,这在很多框架和库中被广泛使用&#…

通信原理实验:FSK调制及解调实验

目录 一、实验目的和要求 二、实验内容和原理 实验器材 实验原理 三、实验步骤 实验项目一 FSK 调制 实验项目二 FSK 解调 四、实验记录与处理(数据、图表、计算等) FSK 调制原理 FSK 解调原理 五、实验结果及分析 一、实验目的和要求 掌握用键控法产生 FSK 信号的…

OD E卷 - 实现【流浪地球】

文章目录 题目解题代码 题目 在赤道上均匀部署N个转向发动机,编号为0 ~ N - 1: 默认 为未启动状态,启动方式为手动启动、关联启动;如果在时刻1一个发动机被启动,在时刻2 与之相邻的两个发动机就会被关联启动&#xf…

[MRCTF2020]Transform

查壳,拖入64位IDA LOBYTE8位就是一个字节,在此处无意义,因为我们输入的本来就是按字节输入的 设 a byte_414040,bdword_40F040,cbyte_40F0E0,输入的字符串为flag; 从题目里得到 加密代码 a[i] flag[b[i]]; a[i] ^ b[i]; c a 即c[i] a[i…

网络安全-AAA介绍与配置

前言 AAA是Authentication(认证)、Authorization(授权)和Accounting(计费)的简称,它提供了认证、授权、计费三种安全功能。AAA可以通过多种协议来实现,目前华为设备支持基于RADIUS&a…

Python轴承故障诊断 (21)基于VMD-CNN-BiTCN的创新诊断模型

往期精彩内容: Python-凯斯西储大学(CWRU)轴承数据解读与分类处理 Pytorch-LSTM轴承故障一维信号分类(一)-CSDN博客 Pytorch-CNN轴承故障一维信号分类(二)-CSDN博客 Pytorch-Transformer轴承故障一维信号分类(三)-CSDN博客 三十多个开源…

【数据结构与算法】链表之美-复杂链表的复制与链表的插入排序

主页:HABUO🍁主页:HABUO 🍁如果再也不能见到你,祝你早安,午安,晚安🍁 1.复杂链表的复制 题目:请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中…