600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 尚硅谷Web前端Promise教程从入门到精通——笔记

尚硅谷Web前端Promise教程从入门到精通——笔记

时间:2024-02-13 15:26:46

相关推荐

尚硅谷Web前端Promise教程从入门到精通——笔记

1. Promise简介

1.1 Promise理解

抽象理解:Promise是js中进行异步编程的新解决方案 异步编程:自己的理解:需要按照一定顺序进行的编程 fs,文件操作ajax数据库操作定时器 之前进行异步编程直接通过回调函数的方式进行,会导致回调地狱 回调函数:作为参数的函数回调地狱:回调函数里面嵌套回调函数 代码可读性差不便于异常处理 具体理解: 从语法上说,Promise是一个构造函数从功能上说,Promise对象用来封装一个异步操作并可以获取其成功/失败的结果值为什么使用PromisePromise支持链式调用,可以解决回调地狱问题 回调地狱: 指定回调函数

1.2 Promise初体验

Promise是一个对象,包含成功、失败等状态,构造函数,then等方法Promise构造函数的参数是一个包含异步操作的函数该函数有两个参数,resolve和reject,这两个参数同样也是函数形式 resolve在函数内的异步操作成功时调用,会将Promise对象状态设置为成功,并且将成功的结果传递给对象,供then的回调函数使用reject在函数内的异步操作失败时调用,会将Promise对象状态设置为失败,并且将失败的原因传递给对象,供then的回调函数使用 Promise.then()函数具有两个参数,都是函数形式 第一个回调函数在Promise状态为成功时调用 其参数value是Promise的构造函数中回调函数中成功的结果 第二个回调函数在Promise状态为失败时调用 其参数reason是Promise的构造函数中回调函数中失败的原因

1.3 Promise实践

1.3.1 fs读取文件

基础回调函数形式:

readFile的第一个参数是文件路径第二个参数是一个回调函数,err表示出错信息,data表示获取到的数据函数主体则根据参数进行操作即可

Promise封装后:

1.3.2 封装fs读取文件

用函数将fs读取操作封装

其返回一个Promise对象

调用函数,使用Promise.then()的方法

原始需要在readFile的参数里面指定回调函数使用Promise后,可以在mineReadFIle后面的then函数中指定回调函数,解决回调地狱问题

1.3.3 util.promisify

作用:自动将异步操作封装成一个Promise

2. Promise属性

2.1 Promise 状态

状态:实例对象中的一个属性 【PromiseState】,三个值

pending:待定,resolved/fullfilled:成功rejected:失败

状态改变

只能由pending改成resolved 或 pending改成rejected状态只能改变一次

2.2 Promise 对象的值

实例对象中的另一个属性 【PromiseResult】保存着异步任务【成功/失败】的结果 只有resolve、reject可以修改其值

3. Promise工作流程

调用构造函数前,Promise的状态为pending调用构造函数,执行异步操作 成功则执行resolved(),修改Promise对象状态为resolved,在then函数中回调onResolved,返回一个新的Promise对象失败则执行rejected(),修改Promise对象状态为rejected,在then函数中回调onRejected,返回一个新的Promise对象

4. 如何使用Promise

4.1 API

Promise构造函数:Promise(executor){}

executor函数:执行器函数(resolve,reject)=>{ }

resolve函数:内部异步操作成功时我们调用的函数

value => { }reject函数:内部异步操作失败时我们调用的函数

reason => { }

PS!!!

executor会在Promise内部立即同步调用,意味着代码执行到Promise的对象创建时就会执行其构造函数的回调函数,再执行下面的代码

如这段代码先输出111再输出222

而执行器的异步操作,就在执行器中按照规定的异步顺序执行

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

Promise.prototype.then()的prototype表示then是Promise的实例对象的方法,如果没有prototype则表示then是promise函数对象的方法(类似于静态方法)

参数为两个回调函数:onResolved,onRejectedonResolved函数:成功的回调函数:

(value)=>{ }onRejected函数:失败的回调函数:

(reason)=>{ }

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

只指定异步操作失败的回调函数,参数只有onRejected onRejected函数:失败的回调函数:

(reason)=>{ }

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

resolve是Promise类的静态方法,不需要实例就能调用

作用:接受一个参数,直接返回一个成功或失败的Promise对象,快速将一个值封装成一个Promise对象使用:特点: 如果传入的参数为非Promise对象,则返回的结果为状态为成功的Promise对象如果传入的参数为Promise对象,则返回的结果为状态为传入的Promise对象的状态,返回结果的值为传入Promise的值 这边会报错是因为传入的Promise状态为rejected,这需要Promise有处理错误的回调函数,通过P2.catch((reason)=>{} )补上回调函数即可相反,如果传入的Promise的状态为resolved,则不需要特意补一个回调函数也不会报错

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

作用:返回一个值为reason的,状态为rejected的Promise对象 无论传入什么都返回一个状态为失败Promise,即使传入一个成功的Promise对象,返回的Promise的值是传入的成功的Promise对象,但是返回Promise的状态还是失败

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

作用:返回一个新的Promise,当所有Promise都成功,返回的Promise状态为成功,其结果为所有Promise的结果组成的一个数组;当存在失败的Promise,返回的Promise的状态为失败,其结果为失败的Promise的结果

成功情况:

失败情况:

4.2 Promise的几个关键问题

4.3.1 改变Promise对象的状态

三种方式 在构造函数中直接调用resolve函数在构造函数中直接调用reject函数在构造函数中直接抛出错误:throw Error

4.3.2 一个Promise指定多个成功/失败的回调函数,都会调用吗

都会执行!

当p的状态变为resolve时,p指定的两个状态变为resolve的回调函数都会执行

4.3.3 改变Promise状态和指定回调函数谁先谁后

问题简化:Promise代码运行时,resolve先执行还是then先执行

注意,指定回调和执行回调函数是不一样的,指定回调类似于p.then()中声明有哪些回调函数,执行回调则是在状态确定之后执行之前指定的回调

两种情况都有可能

先改状态再指定回调: 执行器中是一个同步操作,那么就先做执行器中的操作再执行then语句即指定回调 例如直接在执行器中直接调用 resolve()/reject() 执行器中式一个异步操作,延长更长时间才调用then()同样可以达到效果 先指定回调再改变状态 执行器中式异步操作时,会先执行then,指定回调(但是不执行回调),再回头根据异步操作的顺序进行处理

什么时候能够得到数据?

如果先改变状态,那么当指定回调时,回调函数就会被调用,得到数据如果先指定回调,那么当状态发生改变时,回调函数才被调用得到数据

例子:

promise执行器中是一个异步任务,那么就执行then,指定回调;处理执行器中的异步任务,1000ms后改变状态;再执行成功的回调函数,得到数据

4.3.4 then()方法返回的Promise的对象的状态由什么决定

简单表达:由then()指定的回调函数执行的结果决定

详细表达:

如果回调函数抛出异常,返回Promise状态为【rejected】

如果then()有返回结果,且结果是非Promise对象,例如

则then()方法返回的Promise对象状态为【resolved】,其值为【返回值】,即521

如果then()有返回结果,且结果是Promise对象,例如

则其返回的Promise的状态和值由返回的Promise决定

4.3.5 Promise如何串联多个操作任务

Promise的then()返回一个新的Promise对象,可以形成then方法的链式调用,从而避免回调地狱

let p = new Promise((resolve, reject) => {// 第一次执行异步任务setTimeout(()=>{console.log("first mission")resolve("1000ms later resolve");},1000)})p.then(// 返回一个执行异步任务的Promise,从而第二次执行异步任务,再第一次执行完之后才能执行,链式调用避免回调地狱(value)=>{return new Promise((resolve, reject) => {setTimeout(()=>{console.log("second mission")resolve();},1000)})},).then(value => {return new Promise(resolve => {setTimeout(()=>{console.log("third mission")resolve();},1000)})})

4.3.6 Promise异常穿透?

当使用Promise的then的链式调用时,可以在最后指定失败的回调,而不用每个then都指定一个失败回调

但凡链式调用的过程中由出现失败的情况,最后都会调用最后的失败回调

例如:

then()方法中途返回一个失败的Promise,直接调用最后的catch指定的失败回调

4.3.7 中断Promise链

链式调用过程中,我们希望在某一个then()方法的onResolve回调函数调用过程中,中断Promise的链式调用,只需要返回一个状态为pending的Promise对象

当没有明确返回一个promise对象,then()也会返回一个Promise对象,状态为【resolved】,结果为【underfined】

因为then方法的回调函数调用依据是Promise的状态是resolved或者rejected,没有pending对应的回调函数,所以后面的都没法执行了

例如:

自定义封装看到P31

5. Promise自定义封装

6. async和await

6.1 async

async是一个函数修饰符

函数的返回值是Promise对象

Promise对象的结果由async函数执行的返回值决定

和then一样:分成三种情况执行返回值是非Promise对象,是一个Promise对象,是抛出异常

6.2 await

获取Promise的成功的结果

await右侧表达式一般为Promise对象,但也可以是一个其他值如果表达式时Promise对象,await返回的Promise成功的值如果表达式是其他值,直接将此值作为await的返回值

6.3 async 和 await

理解:async是函数的修饰符,表示这个函数内部可能会存在异步操作;await是一个表达式修饰符,表达式一般跟Promise(内含异步操作),返回的值是Promise成功的值,并且await下面的代码必须要等await后的异步操作完成后才可继续执行,保证了时序

6.3.1 二者联系与区别

await必须要卸载async函数中,async中可以没有await如果await的Promise失败了,会抛出一个异常,需要try catch进行捕获处理

6.3.2 应用例子 — 发送axios请求

6.3.3 应用例子 — 读文件 + 闭包概念

需求:读取多个文件的内容,并将其拼接

使用回调函数的方式进行

所以console.log输出的时候可以访问到 data1和data2

async + await

首先导入util包,利用util.promisify()方法,将readfile方法转化成一个promise对象并返回 利用readfile的Promise对象,使用await修饰,返回文件内的内容给data,之后一次性拼接优点 避免重复回调,可读性高出错可以直接用一个大的try catch包裹,而不用每次回调都抛出错误

Extra:闭包

所以console.log输出的时候可以访问到 data1和data2

async + await

[外链图片转存中…(img-n9QLdX91-1662185609736)]

首先导入util包,利用util.promisify()方法,将readfile方法转化成一个promise对象并返回

[外链图片转存中…(img-WGeX8p3x-1662185609737)]

利用readfile的Promise对象,使用await修饰,返回文件内的内容给data,之后一次性拼接优点 避免重复回调,可读性高出错可以直接用一个大的try catch包裹,而不用每次回调都抛出错误

Extra:闭包

6.3.3 利用到了函数闭包:在上述代码中父对象的变量对于所有子对象都是可见的,反之则不成立;而在我的理解中,闭包是能够读取其他函数内部变量的函数。又因为JavaScript中只有函数内部的子函数才能够获取函数的局部变量,所以在JavaScript中,可以简单理解闭包为:在函数内部的函数

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。