0

0

通过代码实例带你了解Promise

青灯夜游

青灯夜游

发布时间:2023-03-01 20:08:26

|

1924人浏览过

|

来源于掘金社区

转载

本篇文章通过多段代码实例带大家了解 promise 的基础用法,以及更进一步掌握 promise 异步存取的思想。

通过代码实例带你了解Promise

之前一直有听说 Promise 的威名,但是总觉得是个较为深奥的东西,有点畏难而没能真正地去了解。最近看了李立超老师在B站传的 Node.js 的视频,感觉讲的很清晰,自己在这做进一步的梳理。

先来看一个问题

我们都知道 JavaScript 是单线程运行的,所以如果遇到一个数据需要过段时间才能获取到的情况,就会形成阻塞导致后面的代码也无法执行,而这相当致命,比如下面代码

function sum(a, b) {
    const begin = Date.now();
    while(Date.now() - begin < 10000) {

    }
    return a+b;
}

console.log(sum(1,2));
console.log("1");

中间的 while 语句经历了10秒的循环,最终才分别打印出了 3 和 1

然而我们希望的是允许3在10秒后再打印出来,但是1得先打印出来

这里我们就用到了setTimeout,修改代码如下

function sum(a, b) {
    setTimeout(() => {
        return a+b;
    },10000)
}

console.log(sum(1,2));
console.log("1");

运行一下可以看到1确实瞬间被打印出来了,但是本该打印3的位置是undefined

image.png

原因在于此时的console.log同样没有等待setTimeout走完,无法接收到10秒后的数据

所以为了能够接收到这个10秒后的数据,我们可以采用回调函数的方式

function sum(a, b, callback) {

    setTimeout(() =>{
        callback(a+b);
    }, 10000)

}

sum(1,2,(result) => {
    console.log(result);
});
console.log("1");

传入了一个能够接收 a+b 为参数的回调函数 (result) => {console.log(result);}

所以在10秒后会执行这个回调函数,进行打印,结果如下

image.png

这样我们就初步解决了这个问题,一个需要延时获取的数据在其他代码先执行后再被获取。

然而 Promise 还没出现,这就涉及了另一个需要改进的地方

回调地狱

这是个乍一听很唬人的称呼,实际上就是多层回调函数的嵌套导致的不利于阅读和调试的情况。

比如此时我们想要多次调用这个sum函数,要在得到1+2的结果后,再获得 1+2+3,1+2+3+4 这些结果

所以我们得在sum传入的回调函数里再多次调用sum进行嵌套,如下

sum(1,2,(result) => {
    sum(result, 3, (result) => {
        sum(result, 4, (result) => {
            console.log(result);
        })
    })
});

image.png

这种类似金字塔的结构可读性差且不好调试,被称作回调地狱。

所以此时终于到了Promise出场的时候,它的出现解决了回调地狱的问题。

Promise 是什么

在使用Promise解决回调地狱的问题前,先来大致地了解一下什么是Promise。

目前我对它的判断是,Promise 是一个用于存取异步数据的对象。

VALL-E
VALL-E

VALL-E是一种用于文本到语音生成 (TTS) 的语言建模方法

下载

首先来看一下空的 Promise 打印出来会是什么

const promise = new Promise(()=>{});

image.png

其中最关键的就是 PromiseState 和 PromiseResult 两个值,之后会详细展开,这里只要知道Promise中有着这两个属性即可。

接着来看一下 promise 存数据的过程,最关键的就是要知道有 resolve 和 reject,比如下面代码

const promise = new Promise((resolve, reject) => {
    const flag = true;
    if (flag) {
        resolve("resolve datas");
    } else {
        reject("reject data");
    }
})

此时flag为true,所以执行的是resolve的存储,得到的结果如下

image.png

而当我们把flag改为false,执行reject的存储时,得到的结果如下

image.png

现在是解释上面两个属性的时候了,

  • 当 promise 没有存储数据时,PromiseState 的值为 pending,PromiseResult的值为 undefined
  • 当 promise 使用 resolve 存储数据时,PromiseState 的值为 pending,PromiseResult的值为 相应存储值
  • 当 promise 使用 reject 存储数据时,PromiseState 的值为 rejected,PromiseResult的值为相应存储值

既然存有两种类型,读自然也要分两种

当我们读取promise中的数据时,我们需要使用如下的结构

promise.then(result => {
    console.log(result);
}, reason => {
    console.log(reason);
})

如果数据存在resolve中,result会返回结果,如果存在reject中,reason会返回结果。

使用Promise解决回调地狱

在初步了解了Promise后,会发现目前Promise能做的事,使用回调函数也能完成。

所以最主要的还是Promise解决了回调地狱,比如之前的问题,可以写成这种形式

function sum(a, b) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(a+b);
        }, 1000);
    })
}

sum(1,2)
    .then(result => sum(result,3))
    .then(result => sum(result,4))
    .then(result => {
        console.log(result);
    })

promise 通过then方法进行读取后,是个新的Promise对象,比如我们可以打印一下

function sum(a, b) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(a+b);
        }, 1000);
    })
}

console.log(sum(1,2)
    .then(result => sum(result,3)))

image.png

所以这也就给了我们能多次调用then方法的基础。

而这也就解决了回调地狱的问题。

小结

Promise 是一个可以存取异步数据的对象,通过resolvereject来存储数据,可以通过then来读取数据

至于其他的.catch .finally .race .any .all 这些方法就不再多作赘述,详细的见文档

【推荐学习:javascript高级教程

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
chatgpt使用指南
chatgpt使用指南

本专题整合了chatgpt使用教程、新手使用说明等等相关内容,阅读专题下面的文章了解更多详细内容。

0

2026.03.16

chatgpt官网入口地址合集
chatgpt官网入口地址合集

本专题整合了chatgpt官网入口地址、使用教程等内容,阅读专题下面的文章了解更多详细内容。

0

2026.03.16

minimax入口地址汇总
minimax入口地址汇总

本专题整合了minimax相关入口合集,阅读专题下面的文章了解更多详细地址。

4

2026.03.16

C++多线程并发控制与线程安全设计实践
C++多线程并发控制与线程安全设计实践

本专题围绕 C++ 在高性能系统开发中的并发控制技术展开,系统讲解多线程编程模型与线程安全设计方法。内容包括互斥锁、读写锁、条件变量、原子操作以及线程池实现机制,同时结合实际案例分析并发竞争、死锁避免与性能优化策略。通过实践讲解,帮助开发者掌握构建稳定高效并发系统的关键技术。

7

2026.03.16

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

114

2026.03.13

Python异步编程与Asyncio高并发应用实践
Python异步编程与Asyncio高并发应用实践

本专题围绕 Python 异步编程模型展开,深入讲解 Asyncio 框架的核心原理与应用实践。内容包括事件循环机制、协程任务调度、异步 IO 处理以及并发任务管理策略。通过构建高并发网络请求与异步数据处理案例,帮助开发者掌握 Python 在高并发场景中的高效开发方法,并提升系统资源利用率与整体运行性能。

141

2026.03.12

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

396

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

65

2026.03.10

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

111

2026.03.09

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
CSS3 教程
CSS3 教程

共18课时 | 7.3万人学习

Vue 教程
Vue 教程

共42课时 | 9.7万人学习

React 教程
React 教程

共58课时 | 6.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号