一,理解

抽象表达:promise是js中进行异步编程的新的解决方案。(旧的是纯粹的回调函数)
具体表达:从语法上来看,promise是一个构造函数。从功能上来说,promise对象用来封装一个异步操作,并可以获取其结果。

异步操作的第一阶段处理方式:回调函数作为参数传入,异步结果作为回调函数的参数传入,回调函数在异步操作后调用,以完成对异步结果的获取和处理。

之前就学习过,异步操作的执行,是无法直接得到执行结果的。

为了拿到结果,人们将函数作为参数来定义异步操作的函数:

类似于上图这样,利用回调函数作为异步操作的参数传入,在异步操作的函数内部调用回调函数,从而取得异步结果(作为回调函数的参数),并做相应的处理。
也就是说,对异步操作的结果处理放在回调函数中了。
但是,若是出现多层回调函数嵌套的情况,就会产生回调地狱。为了解决回调地狱的问题,人们引入了promise。
所以说它是js中进行异步编程的新的解决方案。

异步操作的第二阶段处理方式:promise

回调地狱的产生,原因还是回调函数对结果的处理和异步操作终究还是在一起,并没有把分离。而引入promise的最大作用,就是把异步操作的过程和结果做到了分离,可以用promise.then()来获取和处理异步操作的结果。

异步操作的第三阶段处理方式:异步函数

promise还是有些繁琐,于是es7又推出了async和await,将同步操作以同步的方式书写出来。

二,promise的状态改变

Promise对象只有三种状态。

异步操作“未完成”(pending)
异步操作“已完成”(resolved,又称fulfilled)
异步操作“失败”(rejected)

这三种的状态的变化途径只有两种且不可逆,且一个promise只能改变以此一次状态。

异步操作从“未完成”到“已完成”
异步操作从“未完成”到“失败”。

因此,Promise对象的最终结果只有两种。要么成功,要么失败。于是只会有一种数据产生,成功的结果数据称value,失败的结果数据称reason

异步操作成功,Promise对象传回一个值,状态变为 resolved。
异步操作失败,Promise对象抛出一个错误,状态变为 rejected。

三,promise的基本运行流程

四,promise的基本使用

const p= new Promise((resolve,reject)=>{  //这个回调函数,又被称之为执行器函数,异步操作放在这里面执行,参数是两个函数(内部定义好了的)//执行异步操作setTimeout(()=>{const time=Date.now()  //如果当前时间是偶数就代表成功//如果成功了,就执行resolve(value),value时成功数据,作为resolve函数的参数if(time % 2 ==0){resolve('成功啦')}else{//如果异步操作失败了,调用reject(reason),reason是作为它的参数reject('失败惹')}},1000)
})
//对异步操作结果的处理
p.then(value=>{    //接收到成功的value数据  onResolvedconsole.log('成功的话就会执行这里的函数---',value)},reason=>{  //接收到失败的reason数据   onRejectedconsole.log('失败的话就会执行这里的函数---',reason)}
)

五,为什么要使用promise

1,指定回调函数的方式更加灵活

旧的纯粹回调函数的形式,必须在启动异步任务前,就指定好回调函数(作为异步操作函数的形参)。而promise,则是启动异步任务,返回promise对象,然后再给promise对象绑定回调函数(甚至可以在异步任务完成后绑定)
例如:使用纯粹的回调函数:

//成功的回调函数
function successCallback(result){//对result的一系列操作,例如下面这行打印结果console.log(result)
}//失败的回调函数
function failureCallback(error){//对error的一系列操作console.log(error)
}//定义异步操作的函数
function createAudioFileAsync(audioSettings,successFun,errorFun){//针对audioSettings中的一些参数,进行异步操作//……一系列的异步操作代码,得成功的话,得到result,失败的话得到errorif(成功){// 执行成功的操作,并将结果传入作为参数successFun(result)}else(失败){// 执行失败后的操作,并将结果传入作为参数errorFun(error)}
}
//1.使用纯粹的回调函数
//使用并进行异步操作,直接指定回调函数,作为异步操作函数的实参传入,使得异步操作的结果也在这个异步操作的函数中处理
createAudioFileAsync(audioSettings,successCallback,failureCallback)
// 2. 使用promise
//直接开始异步操作,只是没有在第一时间完成
const promise = createAudioFileAsync(audioSettings)
//在后面指定的回调函数,异步操作和异步操作的结果做到了分离。
promise.then(successCallback,failureCallback)

2,支持链式调用,可以解决回调地狱问题

什么是回调地狱?回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调函数执行的条件。
回调地狱的缺点?不便于阅读、不便于异步处理
解决方案?promise链式调用
终极解决方案?async/await

// 1. 回调地狱
doSomething(function(result){doSomethingElse(result, function(newResult){doThirdThing(newResult, function(finalResult){console.log('Got the final result:' + finalResult)}, failureCallback)}, failureCallback)
}, failureCallback)// 2. 使用promise的链式调用解决回调地狱
doSomething().then(function(result){return doSomethingElse(result)
})
.then(function(newResult) {return doThirdThing(newResult)
})
.then(function(finalResult){console.log('Got the final result:'+finalResult)
})
.catch(failureCallback)// 3. async/await:回调地狱的终极解决方案
async function request() {try {const result=await doSomething()const newResult=await doSomethingElse(result)const finalResult=await soThirdThing(newResult)console.log('Got the final result'+finalResult)} catch(error) {failureCallback(error)}
}

六,promise的API使用

1、Promise构造函数:Promise(excutor){}

excutor函数:同步执行 (resolve, reject)=>{}
resolve函数:内部定义成功时我们调用的函数 value=>{}
reject函数:内部定义失败时我们调用的函数 reason=>{}
说明:excutor会在Promise内部立即同步回调,异步操作在执行器中执行

2、Promise.prototype.then方法:(onResolved, onRejected)=>{}

onResolved函数:成功的回调函数 (value)=>{}
onRejected函数:失败的回调函数 (reason)=>{}
说明:指定用于得到成功value的成功回调和用于得到失败reason的失败回调,返回一个新的promise对象

3、Promise.prototype.catch方法:(onRejected)=>{}

onRejected函数:失败的回调函数 (reason)=>{}
说明:then()的语法糖,相当于:then(undefined, onRejected)

new Promise((resolve, reject)=>{//一系列异步操作,得到结果result,成功则调用resolve,失败则调用rejectresolve(result)// reject(result)
}).then(  //对成功的结果的处理,参数是一个函数,此函数的参数value就是result,value=>{//函数的内容里面写对异步结果的处理console.log('onResolved()', value)}
).catch(   //对失败的结果的处理,参数是一个函数,此函数的参数reason就是result,reason=>{console.log('onRejected()', reason)}
)

4、Promise.resolve方法:(value)=>{}

value: 成功的数据或promise对象
说明:返回一个成功/失败的promise对象

5、Promise.reject方法:(reason)=>{}

reason:失败的原因
说明:返回一个失败的promise对象

// 产生一个成功值为1的promise对象
const p1=new Promise((resolve, reject)=>{resolve(1)
})
// 产生一个成功值为2的promise对象
const p2=Promise.resolve(2)  // 语法糖
const p3=Promise.reject(3)p1.then(value=>{console.log(value)}) //1
p2.then(value=>{console.log(value)}) //2
p3.catch(reason=>{console.log(reason)}) //3

6、Promise.all方法:(promises)=>{}

promises:包含n个promise的数组
说明:返回一个新的promise,只有所有的promise都成功才成功,只要有一个失败了就直接失败

// 产生一个成功值为1的promise对象
const p1=new Promise((resolve, reject)=>{resolve(1)
})
// 产生一个成功值为2的promise对象
const p2=Promise.resolve(2)  // 语法糖
const p3=Promise.reject(3)// 一个失败的话返回失败的数据,成功的话返回成功的数组
const pAll = Promise.all([p1,p2,p3])
pAll.then(values=>{//此时的valuse是一个数组,每一项对应是每个promise的结果【1,2,3】},reason=>{console.log('all onRejected()', reason) // 3}
)

7、Promise.race方法:(promises)=>{}

promises: 包含n个promise数组
说明:返回一个新的promise,第一个完成的promise的结果状态就是最终的结果状态

const pRace = Promise.race([p1,p2,p3])  //不知道谁先完成,一旦有人成功,则取它,其他人不要了
pRace.then(value=>{console.log('race onResolved()', value)},reason=>{console.log('race onRejected()', reason)}
)

七,promise的几个关键问题

1,如何改变promise 的状态

resolve:如果当前是pendding就会变为resolved
reject:如果当前是pendding就会变为rejected
抛出异常:如果当前是pendding就会变为rejected

const p= new Promise((resolve,reject)=>{//resolve(1)  promise变为resolved成功状态//reject(2)   promise变为rejected失败状态//throw new Error('出错了')  抛出异常,promise变为rejected失败异常,reason为抛出的异常throw 3  //抛出异常,promise变为rejected失败状态,reason为抛出的3
})
p.then(value=>{}reason =>{console.log(reason)}
)
p.then(value=>{}reason =>{console.log('第二次'+reason)}
)
//两次都可以执行,也就是说,可以对异步操作的结果做不同的处理

2,改变promise状态和指定回调函数谁先谁后?

先指定回调函数,然后才改变状态:

先改变状态,后指定回调函数:

或者,直接比异步操作结束时间还晚,来指定回调函数:

3,promise的回调函数,都是异步执行的


看这段代码,resolve(1)是同步执行的,.then()也是同步执行的,这时候,状态已经改变,回调函数也指定好了,那么它是同步执行的吗?不,它是异步执行的,可以由------先输出从而判断出来。

4,promise.then()返回的新promise的结果状态是由什么决定的?

(1),简单表达:由then()指定的回掉函数的执行结果决定
(2),详细表达:

1,如果抛出异常,新promise变为rejected状态,reason为抛出的异常
2,如果返回的是非promise的任意值,新promise变为resolved,value为返回的值。
3,如果返回的是另一个新的promise,此promise的结果就会变成新promise的结果

new Promise((resolve,reject)=>{resolve(1)
}).then(value=>{console.log('onResolved1()',value)//return 2//return Promise.resolve(3)//return Promise.reject(4)throw 5},reason=>{console.log('onRejected1()',reason)}
).then(value=>{console.log('onResolved2()',value)},reason=>{console.log('onRejected2()',reason)}
)
//r啥也不return时,返回结果是:onResolved1() 1  onResolved2() underfined ,因为没有指定value的值
//return 2时,即为返回非promise的任意值,新promise变为resolved,value为返回的值2。于是结果onResolved1() 1  onResolved2() 2
//return Promise.resolve(3)时,返回的是另一个新的promise,此promise的结果就会变成新promise的结果3
//于是返回的结果是:onResolved1() 1  onResolved2() 3
//return Promise.reject(4)和上一个一样,返回的最终结果:onResolved1() 1  onRejected2() 4
//throw 5,如果抛出异常,新promise变为rejected状态,reason为抛出的异常
//最终的结果:onResolved1() 1  onRejected2() 5

由此可以知道,链式写promise中,第一个异步操作的promise失败 了并不会导致后续的promise失败,后续的promise的失败与否还是由新promise决定的。

5,promise的异常传透

1,当使用promises的then链式调用时,可以在最后指定失败的回调。
2,前面的任何操作出了异常,都会传递到最后的失败中处理

6,中断promise链

1,当使用promise的then链式调用时,在中间中断,不再调用后面的回调函数。
2,办法:在回调函数中返回一个pendding状态的promise对象


原理就是返回的新promise没有结果,所以就不会继续调用reject或者resolve,所以就中断了这个链……

promise的理解和使用-尚硅谷教程笔记相关推荐

  1. 尚硅谷_CSS3 笔记

    目录 什么是CSS3 选择器 基本选择器及其扩展 属性选择器 伪类与伪元素选择器 css声明的优先级 自定义字体&字体图标 复习1 新的UI方案 文本新增样式 opacity RGBA 文字阴 ...

  2. Java 基础 第3阶段:高级应用——尚硅谷学习笔记(含面试题) 2023年

    Java 基础 第 3 阶段:高级应用--尚硅谷学习笔记(含面试题) 2023 年 Java 基础 第 3 阶段:高级应用--尚硅谷学习笔记(含面试题) 2023 年 第 9 章 异常处理 9.1 异 ...

  3. 尚硅谷 jQuery 笔记(张晓飞 2018)

    title: 尚硅谷 jQuery 笔记 date: 2020-11-24 21:40:50 toc: true description: jQuery是JS的一个封装的库函数集,用于DOM的CRUD ...

  4. B站MySQL(尚硅谷)学习笔记

    B站MySQL基础(尚硅谷)学习笔记 最近在学习数据库技术,并且把视频中的知识点进行了汇总,字数较多,仅供参考. 会持续更新 欢迎读者提出问题与错误,一起交流~ 视频前几集所讲述的基本知识: DB:数 ...

  5. 尚硅谷JavaSE笔记(四)

    系列文章目录 尚硅谷JavaSE笔记(一) 尚硅谷JavaSE笔记(二) 尚硅谷JavaSE笔记(三) 尚硅谷JavaSE笔记(四) 文章目录 十六.File 类与 IO 流 1.java.io.Fi ...

  6. 尚硅谷python全套-尚硅谷Java视频教程,粉丝无数,人手一套尚硅谷教程

    尚硅谷_图解Java数据结构和算法 算法是程序的灵魂,优秀的程序在对海量数据处理时,依然保持高速计算,就需要高效的数据结构和算法支撑. 2.网上数据结构和算法的课程不少,但存在两个问题: 1)授课方式 ...

  7. 尚硅谷vue笔记 详细讲解版(尚硅谷 天禹老师)

    视频:[尚硅谷Vue2.0+Vue3.0全套教程丨vuejs从入门到精通]https://www.bilibili.com/video/BV1Zy4y1K7SH?vd_source=10e3dfac9 ...

  8. 尚硅谷 Git 笔记

    目录 一.Git 下载安装 二.Git 本地操作常用命令 2.1 设置用户签名 2.2 初始化本地库 2.3 查看本地库状态 2.4 添加暂存区 2.5 提交到本地库 2.7 历史版本 2.8 版本穿 ...

  9. Maven:你还在手动导包吗?带你了解Maven的前世今生(尚硅谷详细笔记)

    文章目录 一.吐槽: 二.为什么要用Maven? 2.1 真的需要吗? 2.2 究竟为什么? 三.什么是Maven? 3.1 Maven 简介 3.2 什么是构建 3.3 构建过程的几个主要环节 3. ...

  10. 尚硅谷_Redis6笔记

    该博客参考尚硅谷Redis6视频资料完成,仅用于学习使用,如有侵权,请联系删除 1.NoSQL数据库简介 1.NoSQL数据库 1.NoSQL数据库概述 NoSQL(NoSQL = Not Only ...

最新文章

  1. pytorch 与 numpy 的数组广播机制
  2. java11 是长期支持_这里有你不得不了解的Java 11版本特性说明
  3. php 批量导出excel文件,PHPEXCEL批量导出
  4. python入门指南 小说-Python入门指南 作者:许半仙(4)
  5. Java NIO学习系列二:Channel
  6. Kibana查询ES显示hits.total.value最大值10000的解决方法
  7. thinkphp URL相关
  8. 微服务网关-Gateway-LoadBalancerClient实现负载均衡讲解
  9. Office Outlook 2007连接Exchange 2007图示(POP3IMAP)
  10. 光端机常见故障问题及其解决方案
  11. Mac下关于-您不能拷贝项目“”,因为它的名称太长或包括的字符在目的宗卷上无效。-的删除...
  12. Oracle:时间字段模糊查询
  13. 台达plc自由口通讯_台达PLC和ABB机器人Devicenet通讯
  14. 计组之数据运算:5、加减运算与溢出判断
  15. redis分布式锁的复杂实现
  16. css控制图片自适应大小
  17. 微信小程序倒计时组件
  18. 记录第一次用阿里云(Windows主机)部署SSM项目(Spring+SpringMVC+Mybatis)
  19. 计算机辅助设计表现的发展给设计带来的影响,计算机辅助设计对艺术设计的影响.doc...
  20. 百度网盘网页版——文件排序

热门文章

  1. html自动旋转屏幕,求教!HTML5屏幕旋转90度再让画布自适应,该如何做,大神给留demo...
  2. 使用DIME协议上传文件
  3. 跟小丸子学基础口语16-20
  4. Panabit安装snmp插件
  5. leetcode链表--1、深拷贝链表
  6. mysql -prompt选项
  7. AJAX 数据库实例
  8. html5中关于input使用方法的改变
  9. SQL*Plus和iSQL*Plus的区别(oracle)
  10. docker网络、bridge、host