Web前端Promise

07-19 1191阅读

Promise介绍与使用

Promise是什么?

1.抽象表达:

  • Promise是一门新的技术(ES6规范)
  • Promise是JS中进行异步编程的新解决方案
  • 备注:旧方案是单纯使用回调函数

    2.具体表达:

    • 从语法上来说:Promise是一个构造函数
    • 从功能上来说:Promise对象用来封装一个异步操作并可以获取其成功/失败的结果值

      异步编程

      • fs文件操作
        require('fs').readFile('./index.html',(err,data)=>{})
        • 数据库操作
        • AJAX
          $.get('/server',(data)=>{})
          • 定时器
            setTimeout(()=>{},2000)

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

            1.旧的:必须在启动异步任务前指定

            2.promise:启动异步任务=>返回promise对象=>

            给promise对象绑定回调函数(甚至可以在异步任务结束后指定/多个) 

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

            回调地狱

            回调地狱嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行的条件

            特点:不便于阅读,不便于异常处理

            Promise实践练习-fs模块

            const fs=require('fs')
            // 回调函数形式
            // fs.readFile('./resource/content.txt',(err,data)=>{
            //   // 如果出错 则抛出错误
            //   if(err) throw err
            //   // 输出文件内容
            //   console.log(data.toString())
            // })
            // Promise形式
            let p=new Promise((resolve,reject)=>{
              fs.readFile('./resource/content.txt',(err,data)=>{
                // 如果出错
                if(err)reject(err)
                  // 如果成功
                resolve(data)
              })
            })
            p.then(value=>{
              console.log(value.toString())
            },reason=>{
              console.log(reason)
            })
            

             Promise实践练习-AJAX请求

            
            
              
              
              Document
            
            
              
                

            Promise 封装AJAX操作

            点击发送AJAX // 接口地址 http://api.apiopen.top/getJoke // 获取元素对象 const btn=document.querySelector('#btn') btn.addEventListener('click',function(){ const p=new Promise((resolve,reject)=>{ // 1.创建对象 const xhr=new XMLHttpRequest() // 2.初始化 xhr.open('GET','https://api.apiopen.top/getJoke') // 3.发送 xhr.send() // 4.处理响应结果 xhr.onreadystatechange=function(){ if(xhr.readyState===4){ // 判断响应状态码 if(xhr.status>=200&&xhr.status{ console.log(value) },reason=>{ console.warn(reason) }) })

            封装读取文件函数

            /**
             *封装一个函数mineReadFile读取文件内容
             参数:path 文件路径
             返回:promise 对象 
             **/
            function mineReadFile(path){
              return new Promise((resolve,reject)=>{
                require('fs').readFile(path,(err,data)=>{
                  // 判断
                  if(err) reject(err)
                    // 成功
                  resolve(data)
                })
              })
            }
            mineReadFile('./resource/content.txt').then(value=>{
              console.log(data)
            },reason=>{
              console.warn(reason)
            })

            util.promisify(original)

            传入一个遵循常见错误优先的回调风格的函数(即以(err,value)=>...回调作为最后一个参数),并返回一个返回promise的版本

            // util.promisify方法
            // 引入util模块
            const util=require('util')
            // 引入fs模块
            const fs=require('fs')
            // 返回一个新的函数
            let mineReadFile=util.promisify(fs.readFile)//让fs.readFile返回一个promise对象,将回调函数风格的方法转为promise风格的方法
            mineReadFile('./resource/content.txt').then(value=>{
            },reason=>{
            })

            Promise封装练习

            
            
              
              
              Document
            
            
              
                // 封装一个函数sendAJAX发送GET AJAX请求
                // 参数   URL
                // 返回结果 Promise对象
                function sendAJAX(url){
                  return new Promise((resolve,reject)=>{
                    const xhr=new XMLHttpRequest()
                    xhr.responseType='json'
                    xhr.open('GET',url)
                    xhr.send()
                    // 处理结果
                    xhr.onreadystatechange=function(){
                      if(xhr.readyState===4){
                        // 判断成功
                        if(xhr.status>=200&&xhr.status{
                  console.log(value)
                },reason=>{
                  console.warn(reason)
                })
              
            
            

            Promise的状态改变

            1. pending变为resolved
            2. pending变为rejected

            说明:只有这两种,且一个promise对象只能改变一次,无论变为成功还是失败,都会有一个结果数据,成功的结果数据一般称为value,失败的结果数据一般称为reason

             Promise的状态

            实例对象中的一个属性PromiseState

            • pending 未决定的
            • resolved/fullfilled成功
            • rejected失败

              Promise对象的值

              实例对象中的另一个属性 PromiseResult

              保存着异步任务(成功或失败)的结果

              Promise的基本流程

              Web前端Promise API

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

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

                说明:executor会在Promise内部立即同步调用(非异步),异步操作在执行器中执行

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

                1. onResolved函数:成功的回调函数(value)=>{}
                2. onRejected函数:失败的回调函数(reason)=>{}

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

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

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

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

                  • value:成功的数据或promise对象

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

                    如果传入的参数为非promise类型的对象,则返回的结果为成功promise对象

                    如果传入的参数为Promise对象,则参数的结果决定了resolve的结果

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

                    • reason:失败的原因

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

                      无论传入什么样的数值,结果均为失败的promise对象

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

                      • promises:包含n个promise的数组

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

                                let p1 = new Promise((resolve, reject) => {
                                    resolve('ok');
                                })
                                let p2 = new Promise((resolve, reject) => {
                                    resolve('hello');
                                })
                                let p3 = new Promise((resolve, reject) => {
                                    reject('error');
                                })
                                let result = Promise.all([p1, p2, p3]);
                                console.log(result);

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

                        • promises:包含n个promise的数组

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

                          Promise.race方法是需要传递一个参数,参数为数组,数组中的内容表示的是Promise实例化对象如果有最先到达状态的(pending来更改成fulfilled或者是rejected),不管是成功状态还是失败的状态,都将以这个对象的状态和结果值为准

                           

                                  const p1 = new Promise((resolve, reject) => {
                                      setTimeout(() => {
                                          resolve(1);
                                      }, 1000)
                                  })
                                  const p2 = new Promise((resolve, reject) => {
                                      setTimeout(() => {
                                          reject(2);
                                      }, 3000)
                                  })
                                  const p3 = new Promise((resolve, reject) => {
                                      setTimeout(() => {
                                          resolve(3);
                                      }, 5000)
                                  })
                                  const result = Promise.race([p3, p1, p2]);
                                  console.log(result);

                          promise的几个关键问题

                          如何改变promise的状态?

                          1. resolve(value):如果当前是pending就会变为resolved
                          2. reject(reason):如果当前是pending就会变为rejected
                          3. 抛出异常:如果当前是pending就会变为rejected
                                  let p1 = new Promise((resolve, reject) => {
                                      //成功
                                      // resolve('success');
                                      //失败
                                      // reject('error');
                                      //抛出异常
                                      // throw ' 出问题啦,你如果在这么写肯定是有问题的,有没有良心~~~';
                                      //状态只能更改一次
                                      reject('error');
                                      resolve('ok');
                                  })
                                  console.log(p1);

                          一个promise指定多个成功/失败回调函数,都会调用吗?

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

                                  let p1 = new Promise((resolve, reject) => {
                                      // resolve('ok');
                                      // reject('error');
                                      // throw '异常'
                                  })
                                  console.log(p1);
                                  p1.then(value => {
                                      console.log(value);
                                  }, reason => {
                                      console.log(reason);
                                  })
                                  p1.then(value => {
                                      console.log(value);
                                  }, reason => {
                                      console.log(reason);
                                  })

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

                          (1)都有可能,正常情况下是先指定回调函数再改变状态,但也可以先改状态再指定回调

                          若执行器函数中为同步任务,则先修改状态,后指定回调

                          若执行器函数中为异步任务,则先指定回调,在更改状态,更为常见 [promise主要是为了执行异步任务]

                          (2)如何先改状态再指定回调?

                          1. 在执行器中直接调用resolve()/reject()
                          2. 延迟更长时间才调用then()

                          (3)什么时候才能得到数据?

                          1. 如果先指定的回调,那当状态发生改变时,回调函数就会调用,得到数据
                          2. 如果先改变的是状态,那当指定回调时,回调函数就会调用,得到数据

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

                          1. 简单表达:由then()指定的回调函数执行的结果决定
                          2. 详细表达:
                          • 如果抛出异常,新promise变为rejected,reason为抛出的异常
                          • 如果返回的是非promise的任意值,新promise变为resolved,value为返回的值
                          • 如果返回的是另一个新promise,此promise的结果就会成为新promise的结果
                                    const p1 = new Promise((resolve, reject) => {
                                        resolve('ok');
                                    })
                                    const result = p1.then(value => {
                                        //console.log(value);
                                        // return value;
                                        return new Promise((resolve, reject) => {
                                            //resolve('success');
                                            reject('error');
                                        })
                                    }, reason => {
                                        console.log(reason);
                                    })
                                    console.log(result);

                            (5)promise如何串连多个操作任务?

                            1. promise的then()返回一个新的promise,可以开成then()的链式调用
                            2. 通过then的链式调用串连多个同步/异步任务
                                    new Promise((resolve, reject) => {
                                        //reject('error');
                                        resolve('success');
                                    }).then(value => {
                                        console.log(value);
                                        console.log(222);
                                    }).then(value => {
                                        console.log(value);//返回结果为undefined
                                    }).then(value => {
                                        console.log(value);
                                    }, reason => {
                                        console.log(reason);
                                    })

                            (6)promise异常穿透

                            1. 当使用promise的then链式调用时,可以在最后指定失败的回调
                            2. 前面任何操作出了异常,都会传到最后失败的回调中处理
                                    new Promise((resolve, reject) => {
                                        console.log(111);
                                        reject('error');
                                    }).then(value => {
                                        console.log(222);
                                    }).then(value => {
                                        console.log(value);
                                    }).then(value => {
                                        console.log(value);
                                    }).catch(reason => {
                                        console.log(reason);
                                    })

                            (7)中断promise链

                            1. 当使用promise的then链式调用时,在中间中断,不再调用后面的回调函数
                            2. 办法:在回调函数中返回一个pendding状态的promise对象
                                    new Promise((resolve, reject) => {
                                        resolve(1);
                                    }).then(value => {
                                        console.log(value);
                                    }).then(value => {
                                        console.log(22222);
                                    }).then(value => {
                                        console.log(33333);
                                        //return false;
                                        //throw '异常';
                                        return new Promise(() => { })
                                    }).then(value => {
                                        console.log(44444);
                                    }).then(value => {
                                        console.log(55555);
                                    }).catch(reason => {
                                        console.log(reason);
                                    })

                            async与await

                            async函数

                            • 函数的返回值为promise对象
                            • promise对象的结果由async函数执行的返回值决定
                              
                              
                                  
                                  
                                  
                                  async函数
                              
                              
                                  
                                      //以前代码
                                      // const p1 = new Promise((resolve, reject) => {
                                      //     resolve('ok');
                                      // })
                                      // //只不过是从原来的回调地狱写法修改成了回调函数的链式写法,换汤不换药
                                      // //使用async结合await的终极目标:就是同步的代码来完成异步的功能
                                      // p1.then(value => {
                                      //     console.log(value);
                                      // }, reason => {
                                      //     console.log(reason);
                                      // }).then(value => {
                                      //     console.log(value);
                                      // }, reason => {
                                      //     console.log(reason);
                                      // })
                                      //任何的函数都可以被声明成一个async函数
                                      //因为要实现的就是异步功能(定时器、ajax请求...)
                                      //可能是要将实现的功能封装到一个函数之中,为了更好的表示函数之中是异步,所以在函数的前面添加一个async
                                      async function main() {
                                          //函数的内部可以添加任意的语句来执行,但是其真正的目的主要是为了得到一个Promise对象的状态以及结果值
                                          // console.log('哈哈哈哈');
                                          //情况1:返回非Promise对象的数据
                                          // return 100;
                                          //情况2:返回的是Promise对象
                                          //返回的这个Promise实例化对象的状态以及结果值将直接影响结果产生的Promise实例化对象的状态和结果值
                                          // return new Promise((resolve, reject) => {
                                          //     // resolve('ok');
                                          //     reject('error');
                                          // })
                                          //情况3:抛出异常
                                          // throw '出错啦';
                                          throw new Error('出错啦');
                                      }
                                      //调用
                                      let result = main();
                                      result.then(value => {
                                          console.log(value);
                                      }, reason => {
                                          console.log(reason);
                                      })
                                  
                              
                              
                              1. await表达式

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

                                注意:

                                • await必须写在async函数中,但async函数中可以没有await
                                • 如果await的promise失败了,就会抛出异常,需要通过try...catch捕获处理
                                  
                                  
                                      
                                      
                                      
                                      await表达式
                                  
                                  
                                      
                                      
                                          async function main() {
                                              //内部执行异步的功能,并且得到成功的结果数据值
                                              //1、如果await右侧为非Promise类型的数据,await后面的值是什么,得到的结果就是什么
                                              // let rs = await 100;
                                              // console.log(rs);
                                              //2、如果await右侧为Promise成功类型的数据
                                              // let rs = await new Promise((resolve, reject) => {
                                              //     resolve('ok');
                                              // })
                                              // console.log(rs);
                                              // let rs = await Promise.resolve('okk');
                                              // console.log(rs);
                                              //3、如果await右侧为失败的Promise类型数据,需要try...catch来捕获
                                              try {
                                                  // let rs = await new Promise((resolve, reject) => {
                                                  //     reject('error');
                                                  // })
                                                  // console.log(rs);
                                                  let rs = await Promise.reject('error');
                                                  console.log(rs);
                                              } catch (e) {
                                                  console.log(e);
                                              }
                                              //有了try...catch后续的代码将继续执行
                                              console.log(1111);
                                          }
                                          //调用
                                          main();
                                      
                                  
                                  

                                  使用async和await异步读取文件

                                  //1、导入模块
                                  const fs = require('fs');
                                  const { promisify } = require('util');
                                  //2、创建async函数
                                  async function main() {
                                      //读取文件
                                      let myreadfile = promisify(fs.readFile);
                                      try {
                                          let one = await myreadfile('./resource/1.txt');
                                          let two = await myreadfile('./resource/2.txt');
                                          let three = await myreadfile('./resource/3.txt');
                                          console.log(one + two + three);
                                      } catch (e) {
                                          console.log(e);
                                      }
                                  }
                                  //调用函数
                                  main();
VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]