搜索
首页web前端js教程一文带你轻松掌握Promise

一文带你轻松掌握Promise

Feb 10, 2023 pm 07:49 PM
javascriptpromise

一文带你轻松掌握Promise

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

异步编程


想要学习promise,你必须要懂得什么是异步编程!众所周知,js语言是单线程机制。所谓单线程就是按次序执行,执行完一个任务再执行下一个。但是不影响存在同步异步的两种操作,这两种操作做事情其实都是在一条流水线上(单线程),只是这两种操作在单线程上的执行顺序不一样罢了!当js触发到异步任务时,会将异步任务交给浏览器处理,当执行有结果时,会把异步任务的回调函数插入待处理队列的队尾!

我们通俗的去解释一下我们的异步:异步就是从主线程发射一个子线程来完成任务,每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的.

在这里插入图片描述

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

回调函数


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

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

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

这段代码中的 setTimeout 就是一个消耗时间较长的过程,它的第一个参数是个回调函数,第二个参数是毫秒数,这个函数执行之后会产生一个子线程,子线程会等待 1 秒,然后执行回调函数 "text",在文本中输出hello james

setTimeout会在子线程中等待1秒,但是主线程的运行不会受到影响!例如以下代码:

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

在这里会先打印出来123456(主线程),然后一秒后在文本中输出hello davis(子线程)

回调地狱


回调地狱这个词听起来就非常的高大上,想要接触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对象有以下两个特点:

  • 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。

  • 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

两个特点摘自于??阮一峰ES6文章

Promise语法格式

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

出现了new关键字,就明白了Promise对象其实就是一个构造函数,是用来生成Promise实例的。能看出来构造函数接收了一个函数作为参数,该函数就是Promise构造函数的回调函数,该函数中有两个参数resolvereject,这两个参数也分别是两个函数!

简单的去理解的话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是一个构造函数,new之后等于说调用了构造函数,构造函数中传的参数是一个函数,这个函数内的两个参数分别又是两个函数(reslovereject),虽然感觉很绕,但是理清思路会很清晰的!


我们得到对象promise,promise对象中自带有两个方法thencatch,这两个方法中会分别再传入一个回调函数,这个回调函数的目的在于返回你所需要成功或失败的信息!那么怎么去调用这两个回调函数呢?
看下方图可以快速理解:

在这里插入图片描述
这两个函数分别做为参数(reslovereject)传到上方的函数中去了.随后在构造函数的回调函数中写入异步代码(例如:ajax定时器),这里使用了定时器作为例子,如果你想表达的是成功回调,你可以在内部调用函数reslove('一般情况下是后端返回的成功数据)。如果你想表达的是失败回调,你可以调用reject('一般情况下是后端返回的失败信息').

这些就是Promise执行的过程!虽然理解着很绕,但是多读几遍绝对有不一样的收获!

Promise链式

then方法返回的是一个新的Promise实例注意:不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法

实际案例:
我想要实现在一个数组中查看一个帖子,但是我最终的目的是得到这个帖子下面的所有评论,这该怎么实现呢?

实现思路
先从一个接口中获取这个帖子的信息,然后通过该帖子的帖子id从而获取到该帖子下的所有评论

代码如下:

pajax({
    url:"http://localhost:3000/news",
    data : {
        author : "james"
    }
}).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才起作用!(这是因为then方法是Promise 实例所具有的方法,也就是说,then方法是定义在原型对象Promise.prototype上的)====>我们可以打印一下:console.log(Promise.prototype)

在这里插入图片描述
可以看的出来原型对象Promise.prototype中是有then方法的!

Promise.all()

Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例

语法格式:

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

Promise.all()方法接受一个数组作为参数,p1、p2、p3都是 Promise 实例,如果不是,就会调用Promise.reslove() [该方法可自行了解]自动将参数转为 Promise 实例,再进一步处理。

说那么多白话没用,我们可以根据一个案例,就可以明白Promise.all()的用途了。

实际案例:
如果你想实现一个效果:在一个页面中,等到页面中所有的请求返回数据后,再渲染页面,该怎么实现呢?(在实际开发中我们会看到loading加载页面,等数据返回完后,loading加载页面会消失,整个页面就展现出来了,增强用户的体验。)

实现思路:
通过Promise.all()方法,等多个接口全部接收到数据后,再统一进行处理,然后渲染页面

代码如下:

console.log("显示加载中")
const q1 = pajax({
    url:"http://localhost:3000/looplist"
})

const q2 = pajax({
    url:"http://localhost:3000/datalist"
})
Promise.all([q1,q2]).then(res=>{
    console.log(res)
    console.log("隐藏加载中...")
}).catch(err=>{
    console.log(err)
})

代码分析:

在上方代码中,全局打印显示加载中是代替loading的页面,表示该页面现在正是loading页面中,等到q1q2所请求接口都得到返回的信息后,在then方法中接收收据,并且可以进行渲染页面,同时隐藏了loading加载页面!

小结

不论是在前端的项目开发中还是在前端的面试过程中,Promise的地位就是举足轻重的,虽然解决异步编程的终极解决方案是async和await,但是它们也是基于Promise封装而来的,在以往文章中,我就说过,学习编程重要的是搞懂某个技术是怎么实现的,而不是做一个cv侠,多去思考,才能进步。继续加油吧,少年!

【相关推荐:javascript视频教程编程基础视频

以上是一文带你轻松掌握Promise的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:csdn。如有侵权,请联系admin@php.cn删除
JavaScript引擎:比较实施JavaScript引擎:比较实施Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和执行JavaScript代码时,效果会有所不同,因为每个引擎的实现原理和优化策略各有差异。1.词法分析:将源码转换为词法单元。2.语法分析:生成抽象语法树。3.优化和编译:通过JIT编译器生成机器码。4.执行:运行机器码。V8引擎通过即时编译和隐藏类优化,SpiderMonkey使用类型推断系统,导致在相同代码上的性能表现不同。

超越浏览器:现实世界中的JavaScript超越浏览器:现实世界中的JavaScriptApr 12, 2025 am 12:06 AM

JavaScript在现实世界中的应用包括服务器端编程、移动应用开发和物联网控制:1.通过Node.js实现服务器端编程,适用于高并发请求处理。2.通过ReactNative进行移动应用开发,支持跨平台部署。3.通过Johnny-Five库用于物联网设备控制,适用于硬件交互。

使用Next.js(后端集成)构建多租户SaaS应用程序使用Next.js(后端集成)构建多租户SaaS应用程序Apr 11, 2025 am 08:23 AM

我使用您的日常技术工具构建了功能性的多租户SaaS应用程序(一个Edtech应用程序),您可以做同样的事情。 首先,什么是多租户SaaS应用程序? 多租户SaaS应用程序可让您从唱歌中为多个客户提供服务

如何使用Next.js(前端集成)构建多租户SaaS应用程序如何使用Next.js(前端集成)构建多租户SaaS应用程序Apr 11, 2025 am 08:22 AM

本文展示了与许可证确保的后端的前端集成,并使用Next.js构建功能性Edtech SaaS应用程序。 前端获取用户权限以控制UI的可见性并确保API要求遵守角色库

JavaScript:探索网络语言的多功能性JavaScript:探索网络语言的多功能性Apr 11, 2025 am 12:01 AM

JavaScript是现代Web开发的核心语言,因其多样性和灵活性而广泛应用。1)前端开发:通过DOM操作和现代框架(如React、Vue.js、Angular)构建动态网页和单页面应用。2)服务器端开发:Node.js利用非阻塞I/O模型处理高并发和实时应用。3)移动和桌面应用开发:通过ReactNative和Electron实现跨平台开发,提高开发效率。

JavaScript的演变:当前的趋势和未来前景JavaScript的演变:当前的趋势和未来前景Apr 10, 2025 am 09:33 AM

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

神秘的JavaScript:它的作用以及为什么重要神秘的JavaScript:它的作用以及为什么重要Apr 09, 2025 am 12:07 AM

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

Python还是JavaScript更好?Python还是JavaScript更好?Apr 06, 2025 am 12:14 AM

Python更适合数据科学和机器学习,JavaScript更适合前端和全栈开发。 1.Python以简洁语法和丰富库生态着称,适用于数据分析和Web开发。 2.JavaScript是前端开发核心,Node.js支持服务器端编程,适用于全栈开发。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
4 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器