2023/1/11 Web前端Promise从入门到精通
创始人
2024-05-10 16:28:25
0

ES6引入的进行异步编程的解决方案,从语法上说它是一个构造函数。
异步编程包括但不限于:文件操作、数据库操作、AJAX、定时器

为什么要用Promise?
之前进行异步编程直接通过回调函数的方式进行,会导致回调地狱。

  • 回调函数:作为参数的函数
  • 回调地狱:回调函数里面嵌套回调函数
    在这里插入图片描述
    具体理解:
    从语法上说,Promise是一个构造函数
    从功能上说,Promise对象用来封装一个异步操作并可以获取其成功/失败的结果值

1 Promise的初体验

实现:
点击按钮, 1s 后显示是否中奖(30%概率中奖)
若中奖弹出 恭喜您中奖
若未中奖弹出 谢谢参与



Title


Promise初体验

在这里插入图片描述
Promise构造函数的参数是一个包含异步操作的函数

new Promise((resolve, reject) => {})

函数有两个参数,resolve和reject,这两个参数同样也是函数形式

  • resolve在函数内的异步操作成功时调用,会将Promise对象状态设置为成功,并且将成功的结果传递给对象,供then的回调函数使用。
  • reject在函数内的异步操作失败时调用,会将Promise对象状态设置为失败,并且将失败的原因传递给对象,供then的回调函数使用。
const p = new Promise((resolve, reject) => {let n = rand(1, 100)if (n <= 30) {resolve(n) // 将 promise 对象的状态设置为 『成功』} else {reject(n) // 将 promise 对象的状态设置为 『失败』}
     p.then((value) => {alert('恭喜您中奖,您的中奖号码为' + value);}, (reason) => {alert('谢谢参与,您的号码为' + reason);})

Promise.then()函数具有两个参数,都是函数形式

  • 第一个回调函数在Promise状态为成功时调用
    其参数value是Promise的构造函数中回调函数中成功的结果
  • 第二个回调函数在Promise状态为失败时调用
    其参数reason是Promise的构造函数中回调函数中失败的原因

2 fs读取文件

基础回调函数形式:

const fs = require('fs')fs.readFile('D:\\code\\wt-promise\\src\\components\\HelloWorld.vue', (err, data) => {if (err) {throw err;} else {console.log(data.toString())}})
  • readFile的第一个参数是文件路径
  • 第二个参数是一个回调函数,err表示出错信息,data表示获取到的数据
  • 函数主体则根据参数进行操作即可

Promise封装后:

const fs = require('fs')
let p = new Promise((resolve, reject) => {fs.readFile('D:\\code\\wt-promise\\src\\components\\HelloWorld.vue', (err, data) => {// 如果出错if (err) reject(err);// 如果成功resolve(data);});
});p.then(value => {console.log(value.toString());
}, reason => {console.log(reason);
})

3 AJAX请求



Title


Promise封装AJAX 操作



Title


Promise封装AJAX 操作

4 Promise封装fs读取文件操作【真没发现!!!!】

封装一个函数 mineReadFile 读取文件内容

  • 参数: path 文件路径
  • 返回: promise 对象
function mineReadFile(path) {return new Promise((resolve, reject) => {// 读取文件require('fs').readFile(path, (err, data) => {if (err) {reject(err);} else {resolve(data);}});});
}

其返回一个Promise对象

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

mineReadFile('./resource/content.txt').then((value) => {console.log(value.toString());}, (reason) => {console.log(reason);});
  • 原始需要在readFile的参数里面指定回调函数
    在这里插入图片描述

  • 使用Promise后,可以在mineReadFIle后面的then函数中指定回调函数,解决回调地狱问题

5 util.promisify方法进行promise风格转化

作用:自动将异步操作封装成一个Promise
在这里插入图片描述

//  引入util模块
const util=require('util');
// 引入fs模块
const fs=require('fs');
//返回一个新的函数
let mineReadFile=util.promisify(fs.readFile);mineReadFile('./resource/content.txt').then(value=>{console.log(value.toString());
});

7 Promise对象状态属性介绍

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

  • pending 待定
  • resolved / fullfilled 成功
  • rejected 失败
    状态改变:
  • 只能由pending改成resolved 或 pending改成rejected
  • 状态只能改变一次

实例对象中的另一个属性 【PromiseResult】- 对象的值
保存着异步任务『成功/失败』的结果

  • resolve
  • reject
  • 只有resolve、reject可以修改其值

8 Promise工作流程

在这里插入图片描述

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

9 Promise的API

1 构造函数-then-catch

  • 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,onRejected
onResolved函数:成功的回调函数:(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的结果

成功情况:
在这里插入图片描述
在这里插入图片描述
失败情况
在这里插入图片描述
在这里插入图片描述

  • Promise.race()方法 (promises) => {}

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



Title




在这里插入图片描述

10 Promise关键问题

1 如何修改对象的状态

三种方式

  • 在构造函数中直接调用 resolve 函数
  • 在构造函数中直接调用 reject 函数
  • 在构造函数中直接抛出错误:throw Error


Title




在这里插入图片描述

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

当promise状态改变为对应状态时都会调用



Title




在这里插入图片描述

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

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

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

两种情况都有可能

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

什么时候才能得到数据? - 回调函数什么时候执行

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

如下为同步:



Title




在这里插入图片描述

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



Title




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

then方法返回结果由 then()指定的回调函数执行的结果决定



Title




在这里插入图片描述

① 如果抛出异常, 新 promise 变为 rejected, reason 为抛出的异常



Title




在这里插入图片描述

② 如果返回的是非 promise 的任意值, 新 promise 变为 resolved, value 为返回的值



Title




在这里插入图片描述

③ 如果返回的是另一个新 promise, 此 promise 的结果就会成为新 promise 的结果



Title




在这里插入图片描述

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

(1) promise 的 then()返回一个新的 promise, 可以看成 then()的链式调用
(2) 通过 then 的链式调用串连多个同步/异步任务



Title




在这里插入图片描述

6 异常穿透

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



Title




在这里插入图片描述



Title




在这里插入图片描述

7 如何中断promise链

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

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

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


Title




11 async

  • async是一个函数修饰符
  • 函数的返回值是Promise对象
  • Promise对象的结果由async函数执行的返回值决定
和then一样:分成三种情况执行返回值: 是非Promise对象,是一个Promise对象,是抛出异常

在这里插入图片描述

12 await

获取Promise的成功的结果

  • await右侧表达式一般为Promise对象,但也可以是一个其他值
  • 如果表达式时Promise对象,await返回的Promise成功的值
  • 如果表达式是其他值,直接将此值作为await的返回值
await 必须写在 async 函数中, 但 async 函数中可以没有 await
如果 await 的 promise 失败了, 就会抛出异常, 需要通过 try…catch 捕获处理


Title


Promise初体验

在这里插入图片描述

13 async与await结合实践

//回调函数的方式
fs.readFile('D:\\code\\wt-promise\\src\\hello.text', (err, data1) => {if (err) throw err;fs.readFile('D:\\code\\wt-promise\\src\\hello.text', (err, data2) => {if (err) throw err;fs.readFile('D:\\code\\wt-promise\\src\\hello.text', (err, data3) => {if (err) throw err;console.log(data1 + data2 + data3);});});
});

在这里插入图片描述

//async 与 await
async function main() {try {// 如果表达式时Promise对象,await返回的Promise成功的值let data1 = await mineReadFile('D:\\code\\wt-promise\\src\\hello.text');let data2 = await mineReadFile('D:\\code\\wt-promise\\src\\hello.text');let data3 = await mineReadFile('D:\\code\\wt-promise\\src\\hello.text');console.log(data1 + data2 + data3);} catch (e) {console.log(e.code);}
}main();

在这里插入图片描述

14 async与await结合发送AJAX请求

在这里插入图片描述

相关内容

热门资讯

常用商务英语口语   商务英语是以适应职场生活的语言要求为目的,内容涉及到商务活动的方方面面。下面是小编收集的常用商务...
六年级上册英语第一单元练习题   一、根据要求写单词。  1.dry(反义词)__________________  2.writ...
复活节英文怎么说 复活节英文怎么说?复活节的英语翻译是什么?复活节:Easter;"Easter,anniversar...
2008年北京奥运会主题曲 2008年北京奥运会(第29届夏季奥林匹克运动会),2008年8月8日到2008年8月24日在中华人...
英语道歉信 英语道歉信15篇  在日常生活中,道歉信的使用频率越来越高,通过道歉信,我们可以更好地解释事情发生的...
六年级英语专题训练(连词成句... 六年级英语专题训练(连词成句30题)  1. have,playhouse,many,I,toy,i...
上班迟到情况说明英语   每个人都或多或少的迟到过那么几次,因为各种原因,可能生病,可能因为交通堵车,可能是因为天气冷,有...
小学英语教学论文 小学英语教学论文范文  引导语:英语教育一直都是每个家长所器重的,那么有关小学英语教学论文要怎么写呢...
英语口语学习必看的方法技巧 英语口语学习必看的方法技巧如何才能说流利的英语? 说外语时,我们主要应做到四件事:理解、回答、提问、...
四级英语作文选:Birth ... 四级英语作文范文选:Birth controlSince the Chinese Governmen...
金融专业英语面试自我介绍 金融专业英语面试自我介绍3篇  金融专业的学生面试时,面试官要求用英语做自我介绍该怎么说。下面是小编...
我的李老师走了四年级英语日记... 我的李老师走了四年级英语日记带翻译  我上了五个学期的小学却换了六任老师,李老师是带我们班最长的语文...
小学三年级英语日记带翻译捡玉... 小学三年级英语日记带翻译捡玉米  今天,我和妈妈去外婆家,外婆家有刚剥的`玉米棒上带有玉米籽,好大的...
七年级英语优秀教学设计 七年级英语优秀教学设计  作为一位兢兢业业的人民教师,常常要写一份优秀的教学设计,教学设计是把教学原...
我的英语老师作文 我的英语老师作文(通用21篇)  在日常生活或是工作学习中,大家都有写作文的经历,对作文很是熟悉吧,...
英语老师教学经验总结 英语老师教学经验总结(通用19篇)  总结是指社会团体、企业单位和个人对某一阶段的学习、工作或其完成...
初一英语暑假作业答案 初一英语暑假作业答案  英语练习一(基础训练)第一题1.D2.H3.E4.F5.I6.A7.J8.C...
大学生的英语演讲稿 大学生的英语演讲稿范文(精选10篇)  使用正确的写作思路书写演讲稿会更加事半功倍。在现实社会中,越...
VOA美国之音英语学习网址 VOA美国之音英语学习推荐网址 美国之音网站已经成为语言学习最重要的资源站点,在互联网上还有若干网站...
商务英语期末试卷 Part I Term Translation (20%)Section A: Translate ...