ES6 Promise

  1. Pronise介绍与基本使用

    1. Promise的定义:

      概念表达:Promise是一门新的技术,用来解决JS中进行异步编程的新的解决方案

      技术表达:Promise是一个构造函数,用来封装一个异步操作,并且可以获取其成功/失败的结果值。

    2. 常见异步操作
      • fs读写文件
      require('fs').readfile('../index.js','utf-8',(err,data)=>{})
      
      • 数据库操作(例如,mysql模块中的db.querry)
      require('mysql').querry('select * from users',(err,resluts)=>{})
      
      • Ajax数据请求操作
      $.get('/api',(data)=>{})
      
      • 定时器
      setTimeout(()=>{},1000)
      
    3. 为什么要使用Promise
      3.1 支持链式调用,可以解决回地狱的问题
      • 回调地狱:回调函数的嵌套调用,外部回调函数异步执行的结果是嵌套的回调函数执行的条件。
      • 回调函数的确定:①层层嵌套,不便于阅读②不变域异常处理
      • 解决方案:①Promise链式调用
      3.2 指定回调函数的方式更加灵活
      • 旧的回调函数:必须在启动异步任务前指定
      • promise:启动异步任务 => 返回promise对象 => 给promise对象绑定回调函数(甚至可以在异步任务结束后,指定多个回调函数)
    4. Promise封装小案例
    • 封装Ajax请求
    /* 封住一个发送sendAjax发送GET Ajax请求
        参数 URL
        返回 Promise对象 */
        function sendAjax(url){
            return new Promise((resovle,reject)=>{
                const xhr = new XMLHttpRequest();
                xhr.open("GET",url);
                xhr.responseType = 'json';
                xhr.send();
                xhr.onreadystatechange = function(){
                    if(xhr.readyState === 4){
                        // 判断成功
                        if(xhr.status >= 200 &&xhr.status<=400){
                            resovle(xhr.response)
                        }
                        else{
                            reject(xhr.status)
                        }
                    }
                }
            })
        }
        sendAjax('https://api.apiopen.top/api/sentences').then(res=>{
            console.log(res)
        },err=>{
            console.warn(err)
        })
    
    • 封装fs模块
    function readFile(path,method){
    return new Promise((resolve,reject)=>{
        require('fs').readFile(path,method,(err,data)=>{
            // 判断,如果出现错误
            if(err) reject(err);
            // 成功
            resolve(data)
        })
    })
    }
    readFile('./a.txt','utf-8').then(
    value=>{
        console.log(value)
    },
    reason=>{
        console.log(reason)
    }
    );
    
    • util.promisify
    /* 
    util.promisify方法
    */
    const util = require('util')
    const fs = require('fs');
    //  返回一个promise风格的函数
    let readFiles = util.promisify(fs.readFile)
    readFiles('./a.txt').then(value=>{
     console.log(value.toString())
    })
    
    1. Promise的状态改变

    状态:实例对象的一个属性PromiseState

    • pendding 未决定的
    • resolved / fulfilled 成功
    • rejected 失败
    1. Promise对象的值

    实例对象中的另一个属性PromiseResult,保存的是对象异步操作成功/失败的结果,resolve和reject可以对属性PromiseResult进行修改
    7. #### Promise的基本流程
    new Promise()[pendding状态]-----(执行异步操作)----->成功,执行resolve----->Promise对象[resolved]----->新的Promise对象

  2. PromiseAPI

  • Promise构造函数:Promise(excutor){}

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

    (2)resolve函数:内部定义成功时我们调用的函数value =>{}

    (3)reject函数:内部定义失败时我们调用的函数reason =>{}

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

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

    (1)onResolved.函数:成功的回调函数(value) =>{}

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

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

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

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

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

    (1)value:成功的数据或promise对象

    说明:①如果传入的参数为非Promise类型的对象,则返回的结果为成功Promise对象

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

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

    (1)reason:失败的原因

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

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

    (1) promises:包含n个promise的数组

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

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

    (1)promises:包含n个promise的数组

    说明:返回一个新的 promise,由第一个先改变状态的 promise的结果状态就是最终的结果状态

  1. Promise关键问题

3.1. 如何改变promise的状态

(1) resolve(value):如果当前是pending就会变为resolved

(2)reject(reason):如果当前是pending就会变为rejected

(3)抛出异常:如果当前是pending就会变为rejected

3.2. 一个Promise指定多个成功/失败回调函数,都会调用吗?
  • 当Promise改变状态是对应状态的回调都会调用
3.3. 改变Promise状态和指定回到函数谁先谁后?

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

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

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

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

  • 如果先指定的回调,那当状态发生改变时,回调函数就会调用,得到数据
  • 如果先改变的状态,那当指定回调时,回调函数就会调用,得到数据
3.4. promise.then()返回的新promise的结果状态由什么决定?
  • 简单表达:由then()指定的回调函数执行的结果决定‘
  • 详细表达:
    1. 如果得抛出异常,新promise变为rejected,reason为抛出的异常
    2. 如果返回的是非promise的任意值,新promise变为resolved,value为返回的值
    3. 如果返回的是另一个新的Promise,此时then的Promise结果就会变成新的promise的结果
3.5.promise如何串连多个操作任务?

(1)promise的 then()返回一个新的promise,可以开成 then()的链式调用

(2)通过 then的链式调用串连多个同步/异步任务

3.6. Promise异常穿透

(1)当使用promise的 then链式调用时,可以在最后指定失败的回调

(2)前面任何操作出了异常,都会传到最后失败的回调中处理

3.7. 中断Promise链

(1)当使用promise的then链式调用时,在中间中断,不再调用后面的回调函数

(2)解决办法:在回调函数中返回一个pendding 状态的 promise对象

原因:因为返回的是pendding状态的Promise对象,then的返回值为pendding状态的Promise对象,由于状态没有改变,所以后续的resolved和rejected状态的回调函数都不会执行

  1. Promise自定义封装

    class Promise {
        // 构造方法
        constructor(executor) {
            // 添加属性
            this.PromiseState = 'pendding';
            this.PromiseResult = null;
            this.callbacks = [];
            const that = this;
            // resolve函数
            function resolve(data) {
                // 判断状态
                if (that.PromiseState !== "pendding") return;
                // 1.修改Promise的状态(PromiseState)
                that.PromiseState = 'fulfilled';
                // 2.设计Promise对象结果值(PromiseResult)
                that.PromiseResult = data
                // 调用成功的回调函数
                // 应该执行多个成功的回调函数
                setTimeout(() => {
                    that.callbacks.forEach(v => {
                        v.onResovled(data);
                    });
                })
            };
            // reject函数
            function reject(data) {
                // 判断状态
                if (that.PromiseState !== "pendding") return;
                // 1.修改Promise的状态(PromiseState)
                that.PromiseState = 'rejected';
                // 2.设计Promise对象结果值(PromiseResult)
                that.PromiseResult = data
                // 调用失败的回调函数
                // 应该执行多个失败的回调函数
                setTimeout(() => {
                    that.callbacks.forEach(v => {
                        v.onRjected(data);
                    });
                })
    
            };
            try {
                // 执行器函数在Promise内部是同步调用的
                executor(resolve, reject)
            } catch (err) {
                // 修改Promise的状态为失败
                reject(err);
            }
        }
        // then方法封装
        then(onResovled, onRjected) {
            const that = this;
            // 判断回调函数
            if (typeof onRjected !== 'function') {
                onRjected = reason => {
                    throw reason;
                }
            }
            if (typeof onResovled !== 'function') {
                onResovled = value => value
                // value=>{ return value }
            }
            return new Promise((resolve, reject) => {
                // 封装函数
                function callback(funtype) {
                    try {
                        // 获取回调函数的执行结果
                        let res = funtype(that.PromiseResult);
                        // 判断
                        if (res instanceof Promise) {
                            // 如果是Promise类型的对象
                            res.then(res => {
                                resolve(res);
                            }, err => {
                                reject(err);
                            })
                        } else {
                            //返回成功状态的Promise
                            resolve(res)
                        }
                    } catch (err) {
                        reject(err)
                    }
                }
                // 调用回调函数
                if (this.PromiseState === "fulfilled") {
                    setTimeout(() => {
                        callback(onResovled);
                    })
                }
                if (this.PromiseState === "rejected") {
                    setTimeout(() => {
                        callback(onRjected);
                    })
                }
                // 判断pendding状态
                if (this.PromiseState === "pendding") {
                    // 保存回调函数
                    this.callbacks.push(
                        {
                            onResovled: function () {
                                callback(onResovled);
                            },
                            onRjected: function () {
                                callback(onRjected)
                            }
                        }
                    )
                }
            })
        }
    
        // catch方法
        catch(onRjected) {
            return this.then(undefined, onRjected);
        }
    
        // resolve方法
        static resolve(value) {
            // 返回promise对象
            return new Promise((resolve, reject) => {
                if (value instanceof Promise) {
                    value.then(v => {
                        resolve(v)
                    },
                        r => {
                            reject(r);
                        })
                } else {
                    // 状态设置成功
                    resolve(value);
                }
            })
        }
    
        // reject方法
        static reject(reason) {
            return new Promise((resolve, reject) => {
                reject(reason)
            })
        }
        // all方法
        static all(promises) {
            //返回的结果为Promise对象
            return new Promise((resolve, reject) => {
                // 声明变量
                let count = 0;
                let arr = [];
                for (let i = 0; i < promises.length; i++) {
                    promises[i].then(v => {
                        // 每个Promise都成功
                        count++;
                        // 将当前Promise对象成功的结果存入数组中
                        arr[i] = v;
                        if (count === promises.length) {
                            resolve(arr);
                            // count = 0;
                        }
                    }, e => {
                        reject(e);
                    })
                }
            });
        }
        // race方法
        static race(promises) {
            return new Promise((resolve, reject) => {
                for (let i = 0; i < promises.length; i++) {
                    promises[i].then(v => {
                        // 修改状态为成功
                        resolve(v)
                    }, r => {
                        reject(r);
                    })
                }
            })
        }
    }
    
    
  2. async与await

    1. async函数
      • async函数的返回值为promise对象

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

        ①如果返回值是一个非Promise类型的数据,那么整个函数返回的就是一个成功的Promise对象

        ②如果返回的是一个Promise对象,那么整个函数返回的就是的Promise对象的状态

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

      注意:

      • await必须写在nsync函数中,但snync函数中可以没有await

      • 如果await的promise失败了,就会抛出异常,需要通过try…catch捕获处理

        let p = new Promise((resolve,reject)=>{
                    // resolve("OK")
                    reject("Error")
                })
                // let res= await p;
                try {
                    let res= await p;
                } catch (e) {
                    console.log(e)
                }
        
      3.async和await结合小案列
      function sendAjax(url) {
                  return new Promise((resovle, reject) => {
                      const xhr = new XMLHttpRequest();
                      xhr.open("GET", url);
                      xhr.responseType = 'json';
                      xhr.send();
                      xhr.onreadystatechange = function () {
                          if (xhr.readyState === 4) {
                              // 判断成功
                              if (xhr.status >= 200 && xhr.status <= 400) {
                                  resovle(xhr.response)
                              }
                              else {
                                  reject(xhr.status)
                              }
                          }
                      }
                  })
              }
              var btn1 = document.getElementsByClassName('btn')[0];
              btn1.addEventListener('click', async function () {
                  // 获取信息
                  let res = await sendAjax('https://XXX')
                  console.log(res)
              })
      
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值