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

面试手写实现Promise.all

目录
  • 前言
  • 常见面试手写系列
  • Promise.resolve
    • 简要回顾
    • 源码实现
  • Promise.reject
    • 简要回顾
    • 源码实现
  • Promise.all
    • 简要回顾
    • 源码实现
  • Promise.allSettled
    • 简要回顾
    • 源码实现
  • Promise.race
    • 简单回顾
    • 源码实现
  • 结尾

前言

(?﹏?)曾经真实发生在一个朋友身上的真实事件,面试官让他手写一个Promise.all,朋友现场发挥不太好,没有写出来,事后他追问面试官给的模糊评价是基础不够扎实,原理性知识掌握较少... 当然整场面试失利,并不仅仅是这一个题目,肯定还有其他方面的原因。

但是却给我们敲响一个警钟:Promise手写实现、Promise静态方法实现早已经是面试中的高频考题,如果你对其还不甚了解,耽误你10分钟,我们一起干到他懂O(∩_∩)O

常见面试手写系列

最近很想做一件事情,希望可以将前端面试中常见的手写题写成一个系列,尝试将其中涉及到的知识和原理都讲清楚,如果你对这个系列也感兴趣,欢迎一起来学习噢,目前已有66+手写题实现啦!

1. 点击查看日拱一题源码地址(目前已有66+个手写题实现)

2.脚本之家专栏

Promise.resolve

简要回顾

  • Promise.resolve(value) 方法返回一个以给定值解析后的Promise 对象。
  • 如果这个值是一个 promise ,那么将返回这个 promise ;
  • 如果这个值是thenable(即带有"then" 方法),返回的promise会“跟随”这个thenable的对象,采用它的最终状态;否则返回的promise将以此值完成。

这是MDN上的解释,我们挨个看一下

  • Promise.resolve最终结果还是一个Promise,并且与Promise.resolve(该值)传入的值息息相关
  • 传入的参数可以是一个Promise实例,那么该函数执行的结果是直接将实例返回
  • 这里最主要需要理解跟随,可以理解成Promise最终状态就是这个thenable对象输出的值

小例子

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

// 1. 非Promise对象,非thenable对象

Promise.resolve(1).then(console.log) // 1

// 2. Promise对象成功状态

const p2 = new Promise((resolve) => resolve(2))

Promise.resolve(p2).then(console.log) // 2

// 3. Promise对象失败状态

const p3 = new Promise((_, reject) => reject('err3'))

Promise.resolve(p3).catch(console.error) // err3

// 4. thenable对象

const p4 = {

  then (resolve) {

    setTimeout(() => resolve(4), 1000)

  }

}

Promise.resolve(p4).then(console.log) // 4

// 5. 啥都没传

Promise.resolve().then(console.log) // undefined

源码实现

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

Promise.myResolve = function (value) {

  // 是Promise实例,直接返回即可

  if (value && typeof value === 'object' && (value instanceof Promise)) {

    return value

  }

  // 否则其他情况一律再通过Promise包装一下

  return new Promise((resolve) => {

    resolve(value)

  })

}

// 测试一下,还是用刚才的例子

// 1. 非Promise对象,非thenable对象

Promise.myResolve(1).then(console.log) // 1

// 2. Promise对象成功状态

const p2 = new Promise((resolve) => resolve(2))

Promise.myResolve(p2).then(console.log) // 2

// 3. Promise对象失败状态

const p3 = new Promise((_, reject) => reject('err3'))

Promise.myResolve(p3).catch(console.error) // err3

// 4. thenable对象

const p4 = {

  then (resolve) {

    setTimeout(() => resolve(4), 1000)

  }

}

Promise.myResolve(p4).then(console.log) // 4

// 5. 啥都没传

Promise.myResolve().then(console.log) // undefined

疑问

从源码实现中,并没有看到对于thenable对象的特殊处理呀!其实确实也不需要在Promise.resolve中处理,真实处理的地方应该是在Promise构造函数中,如果你对这块感兴趣,马上就会写Promise的实现篇,期待你的阅读噢。

Promise.reject

简要回顾

Promise.reject() 方法返回一个带有拒绝原因的Promise对象。

?

1

2

3

4

5

6

Promise.reject(new Error('fail'))

  .then(() => console.log('Resolved'),

        (err) => console.log('Rejected', err))

// 输出以下内容       

// Rejected Error: fail

//    at <anonymous>:2:16       

源码实现

reject实现相对简单,只要返回一个新的Promise,并且将结果状态设置为拒绝就可以

?

1

2

3

4

5

6

7

8

9

10

11

Promise.myReject = function (value) {

  return new Promise((_, reject) => {

    reject(value)

  })

}

// 测试一下

Promise.myReject(new Error('fail'))

  .then(() => console.log('Resolved'),

        (err) => console.log('Rejected', err))

// Rejected Error: fail

//    at <anonymous>:9:18

Promise.all

简要回顾

Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。这个静态方法应该是面试中最常见的啦

?

1

const p = Promise.all([p1, p2, p3])

最终p的状态由p1、p2、p3决定,分成两种情况。

(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。

(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

const p1 = Promise.resolve(1)

const p2 = new Promise((resolve) => {

  setTimeout(() => resolve(2), 1000)

})

const p3 = new Promise((resolve) => {

  setTimeout(() => resolve(3), 3000)

})

const p4 = Promise.reject('err4')

const p5 = Promise.reject('err5')

// 1. 所有的Promise都成功了

const p11 = Promise.all([ p1, p2, p3 ])

    .then(console.log) // [ 1, 2, 3 ]

      .catch(console.log)

// 2. 有一个Promise失败了

const p12 = Promise.all([ p1, p2, p4 ])

    .then(console.log)

      .catch(console.log) // err4

// 3. 有两个Promise失败了,可以看到最终输出的是err4,第一个失败的返回值

const p13 = Promise.all([ p1, p4, p5 ])

    .then(console.log)

      .catch(console.log) // err4

源码实现

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

Promise.myAll = (promises) => {

  return new Promise((rs, rj) => {

    // 计数器

    let count = 0

    // 存放结果

    let result = []

    const len = promises.length

    if (len === 0) {

      return rs([])

    }

    promises.forEach((p, i) => {

      // 注意有的数组项有可能不是Promise,需要手动转化一下

      Promise.resolve(p).then((res) => {

        count += 1

        // 收集每个Promise的返回值

        result[ i ] = res

        // 当所有的Promise都成功了,那么将返回的Promise结果设置为result

        if (count === len) {

          rs(result)

        }

        // 监听数组项中的Promise catch只要有一个失败,那么我们自己返回的Promise也会失败

      }).catch(rj)

    })

  })

}

// 测试一下

const p1 = Promise.resolve(1)

const p2 = new Promise((resolve) => {

  setTimeout(() => resolve(2), 1000)

})

const p3 = new Promise((resolve) => {

  setTimeout(() => resolve(3), 3000)

})

const p4 = Promise.reject('err4')

const p5 = Promise.reject('err5')

// 1. 所有的Promise都成功了

const p11 = Promise.myAll([ p1, p2, p3 ])

    .then(console.log) // [ 1, 2, 3 ]

      .catch(console.log)

// 2. 有一个Promise失败了

const p12 = Promise.myAll([ p1, p2, p4 ])

    .then(console.log)

      .catch(console.log) // err4

// 3. 有两个Promise失败了,可以看到最终输出的是err4,第一个失败的返回值

const p13 = Promise.myAll([ p1, p4, p5 ])

    .then(console.log)

      .catch(console.log) // err4

// 与原生的Promise.all返回是一致的   

Promise.allSettled

简要回顾

有时候,我们希望等到一组异步操作都结束了,不管每一个操作是成功还是失败,再进行下一步操作。显然Promise.all(其只要是一个失败了,结果即进入失败状态)不太适合,所以有了Promise.allSettled

Promise.allSettled()方法接受一个数组作为参数,数组的每个成员都是一个 Promise 对象,并返回一个新的 Promise 对象。只有等到参数数组的所有 Promise 对象都发生状态变更(不管是fulfilled还是rejected),返回的 Promise 对象才会发生状态变更,一旦发生状态变更,状态总是fulfilled,不会变成rejected

还是以上面的例子为例, 我们看看与Promise.all有什么不同

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

const p1 = Promise.resolve(1)

const p2 = new Promise((resolve) => {

  setTimeout(() => resolve(2), 1000)

})

const p3 = new Promise((resolve) => {

  setTimeout(() => resolve(3), 3000)

})

const p4 = Promise.reject('err4')

const p5 = Promise.reject('err5')

// 1. 所有的Promise都成功了

const p11 = Promise.allSettled([ p1, p2, p3 ])

    .then((res) => console.log(JSON.stringify(res, null,  2)))

// 输出

/*

[

  {

    "status": "fulfilled",

    "value": 1

  },

  {

    "status": "fulfilled",

    "value": 2

  },

  {

    "status": "fulfilled",

    "value": 3

  }

]

*/

// 2. 有一个Promise失败了

const p12 = Promise.allSettled([ p1, p2, p4 ])

    .then((res) => console.log(JSON.stringify(res, null,  2)))

// 输出

/*

[

  {

    "status": "fulfilled",

    "value": 1

  },

  {

    "status": "fulfilled",

    "value": 2

  },

  {

    "status": "rejected",

    "reason": "err4"

  }

]

*/

// 3. 有两个Promise失败了

const p13 = Promise.allSettled([ p1, p4, p5 ])

    .then((res) => console.log(JSON.stringify(res, null,  2)))

// 输出

/*

[

  {

    "status": "fulfilled",

    "value": 1

  },

  {

    "status": "rejected",

    "reason": "err4"

  },

  {

    "status": "rejected",

    "reason": "err5"

  }

]

*/

可以看到:

  • 不管是全部成功还是有部分失败,最终都会进入Promise.allSettled的.then回调中
  • 最后的返回值中,成功和失败的项都有status属性,成功时值是fulfilled,失败时是rejected
  • 最后的返回值中,成功含有value属性,而失败则是reason属性

源码实现

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

Promise.myAllSettled = (promises) => {

  return new Promise((rs, rj) => {

    let count = 0

    let result = []

    const len = promises.length

    // 数组是空的话,直接返回空数据

    if (len === 0) {

      return rs([])

    }

    promises.forEach((p, i) => {

      Promise.resolve(p).then((res) => {

        count += 1

        // 成功属性设置

        result[ i ] = {

          status: 'fulfilled',

          value: res

        }

        if (count === len) {

          rs(result)

        }

      }).catch((err) => {

        count += 1

        // 失败属性设置

        result[i] = {

          status: 'rejected',

          reason: err

        }

        if (count === len) {

          rs(result)

        }

      })

    })

  })

}

// 测试一下

const p1 = Promise.resolve(1)

const p2 = new Promise((resolve) => {

  setTimeout(() => resolve(2), 1000)

})

const p3 = new Promise((resolve) => {

  setTimeout(() => resolve(3), 3000)

})

const p4 = Promise.reject('err4')

const p5 = Promise.reject('err5')

// 1. 所有的Promise都成功了

const p11 = Promise.myAllSettled([ p1, p2, p3 ])

    .then((res) => console.log(JSON.stringify(res, null,  2)))

// 输出

/*

[

  {

    "status": "fulfilled",

    "value": 1

  },

  {

    "status": "fulfilled",

    "value": 2

  },

  {

    "status": "fulfilled",

    "value": 3

  }

]

*/

// 2. 有一个Promise失败了

const p12 = Promise.myAllSettled([ p1, p2, p4 ])

    .then((res) => console.log(JSON.stringify(res, null,  2)))

// 输出

/*

[

  {

    "status": "fulfilled",

    "value": 1

  },

  {

    "status": "fulfilled",

    "value": 2

  },

  {

    "status": "rejected",

    "reason": "err4"

  }

]

*/

// 3. 有两个Promise失败了

const p13 = Promise.myAllSettled([ p1, p4, p5 ])

    .then((res) => console.log(JSON.stringify(res, null,  2)))

// 输出

/*

[

  {

    "status": "fulfilled",

    "value": 1

  },

  {

    "status": "rejected",

    "reason": "err4"

  },

  {

    "status": "rejected",

    "reason": "err5"

  }

]

*/

Promise.race

简单回顾

Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。

?

1

const p = Promise.race([p1, p2, p3])

只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。

?

1

2

3

4

5

6

7

8

9

10

11

12

const p1 = new Promise((resolve, reject) => {

  setTimeout(resolve, 500, 1)

})

const p2 = new Promise((resolve, reject) => {

  setTimeout(resolve, 100, 2)

})

Promise.race([p1, p2]).then((value) => {

  console.log(value) // 2

})

Promise.race([p1, p2, 3]).then((value) => {

  console.log(value) // 3

})

源码实现

聪明的你一定马上知道该怎么实现了,只要了解哪个实例先改变了,那么Promise.race就跟随这个结果,那么就可以写出以下代码

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

Promise.myRace = (promises) => {

  return new Promise((rs, rj) => {

    promises.forEach((p) => {

      // 对p进行一次包装,防止非Promise对象

      // 并且对齐进行监听,将我们自己返回的Promise的resolve,reject传递给p,哪个先改变状态,我们返回的Promise也将会是什么状态

      Promise.resolve(p).then(rs).catch(rj)

    })

  })

}

// 测试一下

const p1 = new Promise((resolve, reject) => {

  setTimeout(resolve, 500, 1)

})

const p2 = new Promise((resolve, reject) => {

  setTimeout(resolve, 100, 2)

})

Promise.myRace([p1, p2]).then((value) => {

  console.log(value) // 2

})

Promise.myRace([p1, p2, 3]).then((value) => {

  console.log(value) // 3

})

结尾

也许你我素未谋面,但很可能相见恨晚。希望这里能成为你的栖息之地,我愿和你一起收获喜悦,奔赴成长。

 

相关文章:

面试手写实现Promise.all

目录 前言常见面试手写系列Promise.resolve 简要回顾源码实现Promise.reject 简要回顾源码实现Promise.all 简要回顾源码实现Promise.allSettled 简要回顾源码实现Promise.race 简单回顾源码实现结尾 前言 (?﹏?)曾经真实发生在一个朋友身上的真实事件&#xff0c;面试官让…...

TCP网络通信编程之字符流

【案例1】 【题目描述】 【 注意事项】 (3条消息) 节点流和处理流 字符处理流BufferedReader、BufferedWriter&#xff0c;字节处理流-BufferedInputStream和BufferedOutputStream (代码均正确且可运行_Studying~的博客-CSDN博客 1。这里需要使用字符处理流&#xff0c;来将…...

佰维存储面向旗舰智能手机推出UFS3.1高速闪存

手机“性能铁三角”——SoC、运行内存、闪存决定了一款手机的用户体验和定位&#xff0c;其中存储器性能和容量对用户体验的影响越来越大。 针对旗舰智能手机&#xff0c;佰维推出了UFS3.1高速闪存&#xff0c;写入速度最高可达1800MB/s&#xff0c;是上一代通用闪存存储的4倍以…...

降龙十八掌

目录 大数据&#xff1a; 1 HIVE&#xff1a; 1.1 HIVE QL 1.1.1 创建表 1.1.2 更新表 1.1.3 常用语句 1.2 hive参数配置 大数据&#xff1a; 1 HIVE&#xff1a; 1.1 HIVE QL DDL中常用的命令有&#xff1a;create&#xff0c;drop&#xff0c;alter&#xff0c;trunc…...

【项目设计】MySQL 连接池的设计

目录 &#x1f449;关键技术点&#x1f448;&#x1f449;项目背景&#x1f448;&#x1f449;连接池功能点介绍&#x1f448;&#x1f449;MySQL Server 参数介绍&#x1f448;&#x1f449;功能实现设计&#x1f448;&#x1f449;开发平台选型&#x1f448;&#x1f449;MyS…...

Ubuntu系统adb开发调试问题记录

Ubuntu系统adb开发调试问题记录 一、adb devices no permissions二、自定义adb server端口三、动态库目录四、USB抓包 一、adb devices no permissions lsusb -t 设备树直观地查看设备的Bus ID和Device Num&#xff0c;lsusb找到对应的PID和VID编辑udev规则 sudo vim /etc/ud…...

【宏定义】——检验条件是否成立,并返回指定的值

文章目录 功能说明实现示例解析扩展 功能说明 宏检验条件是否成立&#xff0c;并返回指定的值 #define TU_VERIFY(...) _GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, UNUSED)(__VA_ARGS__)TU_VERIFY(1) 检验为真&#xff0c;啥也不干TU_VERIFY(0) 校验为假&…...

UE5引擎源码小记 —反射信息注册过程

序 最近看了看反射相关的知识&#xff0c;用不说一点人话的方式来说&#xff0c;反射是程序在运行中能够动态获取修改或调用自身属性的东西。 一开始我是觉得反射用处好像不大&#xff0c;后续查了下一些反射的使用环境&#xff0c;发现我格局小了&#xff0c;我觉得用处不大的…...

Redis缓存预热

说明&#xff1a;项目中使用到Redis&#xff0c;正常情况&#xff0c;我们会在用户首次查询数据的同时把该数据按照一定命名规则&#xff0c;存储到Redis中&#xff0c;称为冷启动&#xff08;如下图&#xff09;&#xff0c;这种方式在一些情况下可能会给数据库带来较大的压力…...

Android 耗时分析(adb shell/Studio CPU Profiler/插桩Trace API)

1.adb logcat 查看冷启动时间和Activity显示时间&#xff1a; 过滤Displayed关键字&#xff0c;可看到Activity的显示时间 那上面display后面的是时间是指包含哪些过程的时间呢&#xff1f; 模拟在Application中沉睡1秒操作&#xff0c;冷启动情况下&#xff1a; 从上可知&…...

保护隐私与安全的防关联、多开浏览器

随着互联网的不断发展&#xff0c;我们越来越离不开浏览器这个工具&#xff0c;它为我们提供了便捷的网络浏览体验。然而&#xff0c;随着我们在互联网上的活动越来越多&#xff0c;我们的个人信息和隐私也日益暴露在网络风险之下。在这种背景下&#xff0c;为了保护个人隐私和…...

CloudStudio搭建Next框架博客_抛开电脑性能在云端编程(沉浸式体验)

文章目录 ⭐前言⭐进入cloud studio工作区指引&#x1f496; 注册coding账号&#x1f496; 选择cloud studio&#x1f496; cloud studio选择next.js&#x1f496; 安装react的ui框架&#xff08;tDesign&#xff09;&#x1f496; 安装axios&#x1f496; 代理请求跨域&#x…...

【FPGA IP系列】FIFO深度计算详解

FIFO(First In First Out)是一种先进先出的存储结构&#xff0c;经常被用来在FPGA设计中进行数据缓存或者匹配传输速率。 FIFO的一个关键参数是其深度&#xff0c;也就是FIFO能够存储的数据条数&#xff0c;深度设计的合理&#xff0c;可以防止数据溢出&#xff0c;也可以节省…...

JavaScript中语句和表达式

在JavaScript编程中&#xff0c;Statements和Expressions都是代码的构建块&#xff0c;但它们有不同的特点和用途。 ● Statements&#xff08;语句&#xff09;是执行某些操作的完整命令&#xff1b;每个语句通常以分号结束。例如&#xff0c;if语句、for语句、switch语句、函…...

打卡力扣题目十

#左耳听风 ARST 打卡活动重启# 目录 一、题目 二、解决方法一 三、解决方法二 关于 ARTS 的释义 —— 每周完成一个 ARTS&#xff1a; ● Algorithm: 每周至少做一个 LeetCode 的算法题 ● Review: 阅读并点评至少一篇英文技术文章 ● Tips: 学习至少一个技术技巧 ● Shar…...

UniApp实现API接口封装与请求方法的设计与开发方法

UniApp实现API接口封装与请求方法的设计与开发方法 导语&#xff1a;UniApp是一个基于Vue.js的跨平台开发框架&#xff0c;可以同时开发iOS、Android和H5应用。在UniApp中&#xff0c;实现API接口封装与请求方法的设计与开发是一个十分重要的部分。本文将介绍如何使用UniApp实…...

利用小波分解信号,再重构

function [ output_args ] example4_5( input_args ) %EXAMPLE4_5 Summary of this function goes here % Detailed explanation goes here clc; clear; load leleccum; s leleccum(1:3920); % 进行3层小波分解&#xff0c;小波基函数为db2 [c,l] wavedec(s,3,db2); %进行…...

QT数据库编程

ui界面 mainwindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h" #include <QButtonGroup> #include <QFileDialog> #include <QMessageBox> MainWindow::MainWindow(QWidget* parent): QMainWindow(parent), ui(new Ui::M…...

基于stm32单片机的直流电机速度控制——LZW

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 一、实验目的二、实验方法三、实验设计1.实验器材2.电路连接3.软件设计&#xff08;1&#xff09;实验变量&#xff08;2&#xff09;功能模块a&#xff09;电机接收信号…...

实际项目中使用mockjs模拟数据

项目中的痛点 自己模拟的数据对代码的侵入程度太高&#xff0c;接口完成后要删掉对应的代码&#xff0c;导致接口开发完后端同事开发完&#xff0c;前端自己得加班&#xff1b;接口联调的时间有可能会延期&#xff0c;接口完成的质量参差不齐&#xff1b;对于数据量过大的模拟…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

ESP32读取DHT11温湿度数据

芯片&#xff1a;ESP32 环境&#xff1a;Arduino 一、安装DHT11传感器库 红框的库&#xff0c;别安装错了 二、代码 注意&#xff0c;DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

uniapp手机号一键登录保姆级教程(包含前端和后端)

目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号&#xff08;第三种&#xff09;后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...

LRU 缓存机制详解与实现(Java版) + 力扣解决

&#x1f4cc; LRU 缓存机制详解与实现&#xff08;Java版&#xff09; 一、&#x1f4d6; 问题背景 在日常开发中&#xff0c;我们经常会使用 缓存&#xff08;Cache&#xff09; 来提升性能。但由于内存有限&#xff0c;缓存不可能无限增长&#xff0c;于是需要策略决定&am…...