Promise难懂?一篇文章让你轻松驾驭

news2024/11/16 20:48:57

前言

前端js学习中,让大家最难受的就是异步的问题,解决异步、回调地狱等问题时你必须得学会promise,对于多数前端程序员来说promise简直就是噩梦,本篇文章就是从通俗易懂的角度做为切入点,帮助大家轻松掌握promise

在这里插入图片描述

异步编程

想要学习promise,你必须要懂得什么是异步编程!众所周知,js语言是单线程机制。所谓单线程就是按次序执行,执行完一个任务再执行下一个。但是不影响存在同步和异步的两种操作,这两种操作做事情其实都是在一条流水线上(单线程),只是这两种操作在单线程上的执行顺序不一样罢了!当js触发到异步任务时,会将异步任务交给浏览器处理,当执行有结果时,会把异步任务的回调函数插入待处理队列的队尾!
我们通俗的去解释一下我们的异步:异步就是从主线程发射一个子线程来完成任务,每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。
在这里插入图片描述

该图摘自于菜鸟教程中的异步编程小节,帮助大家更好的理解什么是异步!

回调函数

回调函数的定义非常简单:一个函数被当做一个实参传入到另一个函数(外部函数),并且这个函数在外部函数内被调用,用来完成某些任务的函数。就称为回调函数

回调函数的两种写法(实现效果相同):

const text = () => {
  document.write('hello may')
}
setTimeout(text,1000)
setTimeout(()=>{
	   document.write("hello may")
},1000)

这段代码中的 setTimeout 就是一个消耗时间较长的过程,它的第一个参数是个回调函数,第二个参数是毫秒数,这个函数执行之后会产生一个子线程,子线程会等待 1 秒,然后执行回调函数 “text”,在文本中输出hello may。
setTimeout会在子线程中等待1秒,但是主线程的运行不会受到影响!例如以下代码:

setTimeout(()=>{
    document.write("hello davis")
},1000)
console.log('123456');

回调地狱

回调地狱这个词听起来就非常的高大上,想要接触Promise之前,必须要懂得什么是回调地狱,以及为什么会产生回调地狱?先来看看概念:当一个回调函数嵌套一个回调函数的时候就会出现一个嵌套结构当嵌套的多了就会出现回调地狱的情况。

举个例子:

比如我们发送三个 ajax 请求:

  • 第一个正常发送
  • 第二个请求需要第一个请求的结果中的某一个值作为参数
  • 第三个请求需要第二个请求的结果中的某一个值作为参数

请看以下代码:

$.ajax({
  url: '我是第一个请求',
  type: 'get',
  success (res) {
    // 现在发送第二个请求
    $.ajax({
      url: '我是第二个请求'type:'post',
      data: { a: res.a, b: res.b },
      success (res1) {
        // 进行第三个请求
        $.ajax({
          url: '我是第三个请求',
          type:'post',
          data: { a: res1.a, b: res1.b },
                  success (res2) { 
            console.log(res2) 
          }
        })
      }
    })
  }
})

这种代码看起来属实是折磨人啊!当我们把代码写成这样的时候,就陷入了可维护性差的状态了,代码体验非常的不良好,看一会就给看懵了,为了解决这个问题,于是,就引入了我们的Promise,用Promise去解决回调地狱问题!

Promise

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大,它是一个 ECMAScript 6 提供的类,目的是更加优雅地书写复杂的异步任务。
Promise对象有以下两个特点:

  1. 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
  2. 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

Promise语法格式

new Promise(function (resolve, reject) {
  // resolve 表示成功的回调
  // reject 表示失败的回调
}).then(function (res) {
  // 成功的函数
}).catch(function (err) {
  // 失败的函数
})

出现了new关键字,就明白了Promise对象其实就是一个构造函数,是用来生成Promise实例的。能看出来构造函数接收了一个函数作为参数,该函数就是Promise构造函数的回调函数,该函数中有两个参数resolve和reject,这两个参数也分别是两个函数!
简单的去理解的话resolve函数的目的是将Promise对象状态变成成功状态,在异步操作成功时调用,将异步操作的结果,作为参数传递出去。reject函数的目的是将Promise对象的状态变成失败状态,在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。

代码示例:
        const promise = new Promise((resolve,reject)=>{
            //异步代码
            setTimeout(()=>{
                // resolve(['111','222','333'])
                reject('error')
            },2000)
        })
        promise.then((res)=>{
            //兑现承诺,这个函数被执行
            console.log('success',res);
        }).catch((err)=>{
            //拒绝承诺,这个函数就会被执行
            console.log('fail',err);
        })

Promise链式

then方法返回的是一个新的Promise实例(注意:不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。
我想要实现在一个数组中查看一个帖子,但是我最终的目的是得到这个帖子下面的所有评论,这该怎么实现呢?

代码如下:
ajax({
    url:"http://localhost:3000/news",
    data : {
        author : "may"
    }
}).then(res=>{
    return pajax({
        url : "http://localhost:3000/comments",
        data : {
            newsId : res[0].id
        }
    })
}).then(res=>{
    console.log(res);
}).catch(err=>{
    console.log(err);
})

这里使用了一个Promise已经封装过的ajax,我们从第一个接口中得到了帖子id,然后在then中的函数发送第二个请求(携带了第一个请求返回过来的参数),我们最后想要拿到第二个接口的结果,于是又有了一个then方法,但是在第一个then方法中要把一个新的Promise实例return出去,这样的话,第二个then才起作用!

小结

不论是在前端的项目开发中还是在前端的面试过程中,Promise的地位就是举足轻重的,虽然解决异步编程的终极解决方案是async和await,但是它们也是基于Promise封装而来的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/107864.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何使用报表工具FastReport VCL 设计器中的 PDF/A?

Fastreport是目前世界上主流的图表控件,具有超高性价比,以更具成本优势的价格,便能提供功能齐全的报表解决方案,连续三年蝉联全球文档创建组件和库的“ Top 50 Publishers”奖。 慧都科技是Fast Reports在中国区十余年的友好合作…

0基础学python容易吗?零基础学习路线目标

零基础Python学习路线及阶段学习目标,首先应该夯实Python核心基础、Web前端编程、Django开发框架、Flask开发框架、爬虫与数据分析等知识,理解机器学习相关的基本概念及系统处理流程。 零基础Python学习路线及阶段学习目标: 阶段一、Python核…

【React学习】React更新渲染原理

当我们调用 setState 之后发生了什么?react经历了怎样的过程将新的 state 渲染到页面上? 一次react更新,核心就是对虚拟dom进行diff,找出最少的需要变化的dom节点,然后对其进行相应的dom操作,用户即可在页…

亲子游小程序开发,助力商家掌握亲子流量

随着新生代父母越来越年轻化,育儿观念上也发生了很大改变,当代父母已经不在单纯的关注孩子的学习情况,学习固然重要但是孩子的身心健康也是非常重要的。所以很多父母开始带着自己的孩子参加各种各样的亲子活动,多参加亲子活动可以…

Python数据分析之Pandas库

Python数据分析之Pandas库一、Pandas简介二、Pandas库的安装三、Pandas的数据结构四、Series 和 DataFrame 数据结构的使用五、其他可以参考的网站一、Pandas简介 Pandas是python的一个数据分析包,最初由AQR Capital Management于2008年4月开发,并于200…

Struts2框架中的Action接口和ActionSupport类

Struts2框架中的Action接口和ActionSupport类1、Action接口2、ActionSupport类3、登录案例3.1、页面3.2、控制器3.3、struts.xml配置3.4、测试1、Action接口 Action是Struts2框架的核心,因为它们适用于任何MVC(Model View Controller)框架。…

【Maven基础】单一架构案例(二)

第三节 搭建环境&#xff1a;事务控制 1、总体思路 2、TransactionFilter 2.1、创建 Filter 类 2.2、TransactionFilter 完整代码 public class TransactionFilter implements Filter {// 声明集合保存静态资源扩展名private static Set<String> staticResourceExtNam…

长时间序列遥感数据处理及在全球变化、物候提取、植被变绿与固碳分析、生物量估算与趋势分析等领域中的实践技术应用

【查看原文】长时间序列遥感数据处理及在全球变化、物候提取、植被变绿与固碳分析、生物量估算与趋势分析等领域中的实践技术应用 植被是陆地生态系统中最重要的组分之一&#xff0c;也是对气候变化最敏感的组分&#xff0c;其在全球变化过程中起着重要作用&#xff0c;能够指…

云知声: 基于 JuiceFS 的超算平台存储实践

云知声从一家专注于语音及语言处理的技术公司&#xff0c;现在技术栈已经发展到具备图像、自然语言处理、信号等全栈式的 AI 能力&#xff0c;是国内头部人工智能独角兽企业。公司拥抱云计算&#xff0c;在智慧医疗、智慧酒店、智慧教育等方面都有相应的解决方案。 Atlas 是云知…

技术栈入门------RabbitMQ

Direct交换机是路由键精准匹配 Fanout交换机是不看路由键 &#xff0c;只要你消息发给了某个交换机&#xff0c;这个交换机就立马把消息转给绑定了这个交换机的所有队列&#xff0c;所以速度最快 Topic交换机可以把一个消息根据交换机和消息队列的绑定的路由键进行匹配&#xf…

没有二十年功力,写不出Thread.sleep(0)这一行“看似无用”的代码!

你好呀&#xff0c;我是喜提七天居家隔离的歪歪。 这篇文章要从一个奇怪的注释说起&#xff0c;就是下面这张图&#xff1a; 我们可以不用管具体的代码逻辑&#xff0c;只是单单看这个 for 循环。 在循环里面&#xff0c;专门有个变量 j&#xff0c;来记录当前循环次数。 第…

项目实战之旅游网(一)项目介绍 项目搭建

目录 一.项目介绍 1.功能介绍 2.技术选型 3.实体类 二.项目搭建 1.创建项目 2.adminLTE 3.编写后端首页 4.提取统一后台模板 5.重构后台首页 ************************************************************************* 项目代码地址&#xff1a;等写完这个项目我…

jsoup

1.什么是jsoup jsoup&#xff1a;Java HTML解析器&#xff0c;专为HTML编辑&#xff0c;清理&#xff0c;抓取和XSS安全而构建 2.依赖 <dependency><!-- jsoup HTML parser library https://jsoup.org/ --><groupId>org.jsoup</groupId><artifac…

干货!深入学习必学的模型微调

学习目标 知道微调的原理能够利用微调模型来完成图像的分类任务1.微调 如何在只有6万张图像的MNIST训练数据集上训练模型。学术界当下使用最广泛的大规模图像数据集ImageNet&#xff0c;它有超过1,000万的图像和1,000类的物体。然而&#xff0c;我们平常接触到数据集的规模通…

浅析JWT

Cookie-session 我们都知道JWT一般用于用户登录等需要记住的操作&#xff0c;在谈论JWT之前就不得不谈谈以前的cookie-session登录了 。因为http协议是一种无状态协议&#xff0c;即每次服务端接收到客户端的请求时&#xff0c;都是一个全新的请求&#xff0c;服务器并不知道客…

【从零开始学微服务】08.引入微服务架构的时机

大家好&#xff0c;欢迎来到万猫学社&#xff0c;跟我一起学&#xff0c;你也能成为微服务专家。 在了解引入微服务架构的时机之前&#xff0c;架构设计时一般需要遵循的三个原则。 架构设计三个原则 架构设计一般需要遵循以下三个原则&#xff1a; 合适原则&#xff1a;合适…

NeurIPS'22 | APG:面向CTR预估的自适应参数生成网络

丨目录&#xff1a; 摘要 背景 Method 实验 结语▐ 摘要目前基于深度学习的CTR预估模型&#xff08;即 Deep CTR Models&#xff09;被广泛的应用于各个应用中。传统的 Deep CTR Models 的学习模式是相对静态的&#xff0c;即所有的样本共享相同的网络参数。然而&#xff0c;由…

IntelliJ IDEA中我最爱的10个快捷操作

1. psvm/main快速生成 main() 方法 在日常开发中&#xff0c;我们经常需要写main()方法&#xff0c;这时候您也可以使用main或者psvm命令快速地帮助我们创建出main()方法。 2.sout快速生成println()方法 打印输出一些内容到控制台也是频率很高的一个行为&#xff0c;我们可以…

Pytest断言

&#x1f534;pytest 允许使用标准的python assert 用于验证Python测试中的期望和值。所以并不像unittest的那么丰富。但是我们可以重写。 ❞小例子--介绍 import pytestclass Testnew:def test_num(self):assert 1 "1"def test_dic(self):assert {"QA":…

MySql索引下推知识分享

作者&#xff1a;刘邓忠 Mysql 是大家最常用的数据库&#xff0c;下面为大家带来 mysql 索引下推知识点的分享&#xff0c;以便巩固 mysql 基础知识&#xff0c;如有错误&#xff0c;还请各位大佬们指正。 1 什么是索引下推 索引下推 (Index Condition Pushdown&#xff0c;…