Promise学习(基于B站尚硅谷Promise学习)

异步操作

  1. fs文件(fs是node下的一个模块,可以对磁盘进行修改)
    require('fs').readFile('./index.html',(err,data)=>{})
    
  2. 数据库操作
  3. Ajax
    $.get('/server',(data)=>{})
    
  4. 定时器
    setTimeout(()=>{},2000);
    

基础特点

  1. 支持链式调用,可以解决回调地狱问题
  2. 指定回调函数的方式更加灵活

promise 初步体验

要求:

  1. 设置按钮进行抽奖
  2. 设置一秒延时
  3. 设置30%概率中奖
  4. 出现结果给出弹窗(含有原生与promise形式实现,主要区别在于JS)
    <!DOCTYPE html>
    
    <html lang="en">
    
    <head>
    
     <meta charset="UTF-8">
    
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
    
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
     <title>Document</title>
    
     <style>
    
     button{
    
     width: 200px;
    
     height: 200px;
    
     background-color: blue;
    
     }
    
     </style>
    
    </head>
    
    <body>
    
     <button>点击抽奖</button>
    
     <script>
    
     //生成随机数
    
     function rand(m,n){
    
     //返回向上取整的数值,并控制再m,n之间
    
     return Math.ceil(Math.random() * (n-m+1)) + m + 1 ;
    
     }
    
     //获取元素对象
    
     const btn = document.querySelector('button')
    
     //设置定时器
    
     btn.addEventListener('click',function(){
    
     //Promise对象实例化
    
     //resolve与reject是自定义的两个变量,一般写为这两种
    
     //成功时用resolve,失败时用reject
    
     const p = new Promise((resolve,reject)=>{
    
     setTimeout(() => {
    
     //设置百分之三十的概率中奖
    
     let n = rand(1,100);
    
     if(n<=30){
    
     resolve(); //调用时讲promise的对象设置为成功
    
     }else{
    
     reject(); //调用时讲promise的对象设置为失败
    
     }
    
     },1000)
    
     });
    
     //调用then方法,指定回调函数
    
     p.then((resolve)=>{
    
     alert('恭喜中奖')
    
     },(reject)=>{
    
     alert('再接再厉')
    
     })
    
     })
    
     </script>
    
    </body>
    
    </html>
    

    要求增加:若是成功返回中奖数字

     const p = new Promise((resolve,reject)=>{
    
     setTimeout(() => {
    
     //设置百分之三十的概率中奖
    
     let n = rand(1,100);
    
     if(n<=30){
    
     resolve(n); //调用时讲promise的对象设置为成功
    
     }else{
    
     reject(n); //调用时讲promise的对象设置为失败
    
     }
    
     },1000)
    
     });
    
     //调用then方法,指定回调函数
    
     p.then((value)=>{
    
     alert('恭喜中奖' + value)
    
     },(reason)=>{
    
     alert('再接再厉' + reason)
    
     })
    
     })
    

promise封装fs使用

//创建FS实例对象

const fs = require('fs');

//创建promise对象

let p = new Promise((resolve,reject)=>{

 fs.readFile('./fist.txt',(err,data)=>{

 //如果出错

 if(err){

 reject(err);

 }else{

 resolve(data);

 }

 })

 p.then((value)=>{

 console.log(value.toString());

 },(reason)=>{

 console.log(reason);

 })

})

promise对ajax封装

<!DOCTYPE html>

<html lang="en">

<head>

 <meta charset="UTF-8">

 <meta http-equiv="X-UA-Compatible" content="IE=edge">

 <meta name="viewport" content="width=device-width, initial-scale=1.0">

 <title>Ajax GET 请求</title>

 <style>

 #result{

 width: 200px;

 height: 100px;

 border: solid 1px black;

 }

 </style>

</head>

<body>

 <button>点击发送请求</button>

 <div id="result"></div>

 <script>

 //获取button元素

 const btn = document.getElementsByTagName('button')[0];

 //在div中显示

 const result = document.getElementById('result');

 //绑定button事件

 btn.onclick = function(){

 //创建promise对象

 const p = new Promise((resolve,reject)=>{

 //1.创建对象

 const xhr = new XMLHttpRequest();

 //2.设置初始化,设置请求方法和URL

 xhr.open('POST','https://api.apiopen.top/getJoke');

 //3.发送

 xhr.send();

 //4.时间绑定,处理服务端返回的结果

 //onreadystatechange即获取状态改变

 //readystate是xhr里面的一个属性,表示状态原本有0,1,2,3,4

 //0表示未初始化,1表示open()方法已经调用完毕,2表示send()方法调用完毕

 //3表示服务端返回了部分结果,4表示客户端返回了所有结果

 xhr.onreadystatechange = function(){

 //我们应该在4的时候承接返回结果

 if(xhr.readyState === 4){

 console.log("客户端已经返回了所有结果")

 //判断响应状态码 200 404 403 401 500

 //2开头的都是成功

 if(xhr.status >= 200 && xhr.status < 300){

 //处理结果,行,头,空行,体

 //1.响应行

 //设置result的文本

 resolve(xhr.response);

 }else {

 //输出状态码

 reject(xhr.status)

 }

 }

 }

 });

 //调用then()方法

 p.then(value=>{

 result.innerHTML = value;

 },reason=>{

 result.innerHTML = reason;

 })

 }

 </script>

</body>

</html>

until.promisefy方法进行promise风格转换

const util = require('util');
const fs = require('fs');

const stat = util.promisify(fs.stat);
stat('.').then((stats) => {
  // 运行操作
}).catch((error) => {
  // 处理错误
});
  1. 最后一个参数是函数
  2. 回调函数的参数为 (err, result),前面是可能的错误,后面是正常的结果

promise状态改变

  1. 状态指实例对象中的一个属性:PromiseState
  2. 一共三个属性:pending(未决定的),rejected/fullfilled(成功),resolved(失败)
  3. pending变为resolved(成功时)
  4. pending变为rejected(失败时)
    说明:改变情况只有这两种,只能改变一次,无论成功与否,都会有一个 数据结果,成功的一般时value,失败一般叫reason(主要在回调中实现)

promise对象的值

  1. 实例对象中的另一个属性:PromiseResult
  2. 保存异步任务对象成功或者失败时候的结果
    • 成功存于resolve
    • 失败存于reject

promise基本流程

promote.png


promise中的API

  1. Promise构造函数:Promise(excutor){}
    • executor函数:执行器(resolve,reject)=>{}
    • resolve函数:内部定义成功时我们调用的函数 value=>{}
    • reject函数:内部定义失败时调用的函数 reason=>{}

    说明:executor会在promise内部立即同步调用,异步操作在执行器中运行。

  2. Promise.prototype.then方法:(onResolved,onRejected)=>{}
    • onResolved函数:成功的回调函数(value)=>{}
    • onRejected函数:失败的回调函数(reason)=>{}

    说明:指定用于得到成功的Value的成功回调和用于得到失败的reason的失败回调返回一个新的promise对象

  3. catch方法:(onRejected)=>{},只会捕捉失败时的回调
    • onRejected函数:失败的回调函数(reason)=>{}
  4. Promise.resolve方法:(value)=>{}
    • value:成功的数据或promise对象
    <!DOCTYPE html>
    
    <html lang="en">
    
    <head>
    
     <meta charset="UTF-8">
    
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
    
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
     <title>Document</title>
    
    </head>
    
    <body>
    
     <script>
    
     //如果传入的参数为 非Promise 类型的对象,则返回的结果为成功Promise对象
    
     let p1 = Promise.resolve(521);
    
     //如果传入的参数为 Promise 对象,则参数结果决定了resolve的结果
    
     let p2 = Promise.resolve(new Promise((resolve,reject)=>{
    
     resolve('success');
    
     })
    
     )
    
     </script>
    
    </body>
    
    </html>
    

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

  5. Promise.reject方法:(value)=>{}
    • reason:失败的原因

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

  6. Promise.all方法:(promises)=>{}
    • promises:包含n个promise的数组
    <!DOCTYPE html>
    
    <html lang="en">
    
    <head>
    
     <meta charset="UTF-8">
    
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
    
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
     <title>Document</title>
    
    </head>
    
    <body>
    
     <script>
    
     let p1 = new Promise((resolve,reject)=>{
    
     resolve('OK');
    
     })
    
     let p2 = Promise.resolve("Happy new year")
    
     let p3 = Promise.reject("fail")
    
     const result = Promise.all([p1,p2]);
    
     console.log(result);//此时为成功
    
     const result = Promise.all([p1,p2,p3]);//此时为失败
    
     </script>
    
    </body>
    
    </html>
    

    说明:返回一个新的promise,只有所有的promise都成功才成功,只要有一个失败就失败

  7. Promise.race方法:(promises)=>{}
    • promises:包含n个promise的数组

    说明:返回一个新的promise对象,第一个完成的promise的结果状态就是最终的结果状态。


promise几个关键问题

  1. 修改状态
 <script>

	let p = new Promise((resolve,reject)=>{

	 //1.resolve函数,pending->fulfilled/resolved

	 resolve('OK');

	 //2.reject函数,pending->rejected

	 reject('Fail');

	 //3.抛出错误,pending->rejected

	 throw '出问题了';

	 })

	 </script>
  1. 一个promise指定多个成功/失败回调函数,都会调用吗?
    当promise状态改变后,回调函数都会调用。
  2. 改变promise状态和指定的会叫函数谁先谁后
    • 都有可能,正常情况下时先指定回调再改变状态,但也可以先改变状态再指定回调
    • 如何先改变状态再指定回调:①在执行器executor中直接调用resolve/reject②延迟更长事件才调用
    let p = new Promise((resolve,reject)=>{
    
     resolve('OK');
    
     });
    
     let p = new Promise((resolve,reject)=>{
     //设置一秒的延迟
    
     setTimeout(()=>{
    
     resolve('OK');
    
     },1000)
    
     });
     
     //设置两秒的延迟
    
     setTimeout(()=>{
    
     p.then(value=>{
    
    
    
     },reason=>{
    
    
    
     })
    
     },2000)
    
    • 什么时候能得到数据:①如果先指定的回调,那当状态发生改变时,回调函数就会调用获取数据②如果先改变的状态,那当指定回调时,回调函数就会调用,得到数据
  3. promise.then()返回的新promise的结果状态由上面决定
    • 简单表达:由then()指定的回调函数的执行结果决定
    • 详细描述:①如果抛出异常,新promise变为rejected,reason为抛出的异常②如果返回的时非promise的任何值,新promise变为resolved,value为返回的值③如果返回的是另一个新promise,此promise的结果会成为新promise的结果
  4. promise异常穿透
    • 当使用promise的then链式调用,可以再最后指定失败的回调
    • 前面任何操作出现异常,都会传到最后失败的回调中处理
  5. 终端promise链
    • 返回一个pending状态的promise:
    retuen new Promise(()=>{});
    

async函数

  1. 结果是promise对象

await表达式

  1. await必须卸载async中,但async中可以没有await
  2. 如果await中的promise失败了,就会抛出异常,需要通过try...catch捕获处理

async与await的结合使用

 <script>

 const fs = require('fs');

 const util = require('util');

 const mineReadFile = util.promisfy(fs.readFile);

 async function main(){
	 
	 try{

 let data1 = await mineReadFile('./api.html');

 let data2 = await mineReadFile('./fist.html');

 let data3 = await mineReadFile('./second.html');

 }
 }catch(e){
 console.log(e);
 }

 </script>


async与await结合发送ajax请求

 <script>

 function sendAjax(url){

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

  

 })

 let btn = document.querySelector(#btn);

 btn.addEventListener('click',async function(){

 let content = await sendAjax('http.baidu.com');

 })

 }

 </script>
posted @ 2022-01-21 19:15  SmallCity  阅读(54)  评论(0编辑  收藏  举报