ES——Promise

先看一段代码,这是我们这边普遍的异步通信模式,采用callback的写法,将回调函数层层传入

const func1 = (callback)=> {
  $.ajax({
    ...,
    success: (res)=> {
      console.log('武林要以和为贵');
      func2(callback, res)
    }
  })
}

const func2 = (callback, data)=> {
    $.ajax({
        ...,
        success: (res)=> {
						console.log('要讲武德');
            callback()
        }
    })
}

func1(()=> {
    console.log('不要搞窝里斗');
}) 
//输出结果为:武林要以和为贵,要讲武德,不要搞窝里斗

一、Promise 概览


Promise

  • 语法上讲是一个对象(类),可以用来获取异步操作的内容消息
  • 从本意上讲,被译为期约,是对当前函数调用状态的一种保证
  • 从用途上讲,是异步编程的一种解决方案,比回调函数(callback)和事件(event)更合理

Promise 主要解决两个问题

  • 解决异步问题,实现多并发请求

  • 解决回调地狱

    //有多个异步任务,要求需要同时拿到所有异步任务的结果,下边就是用回调函数的方法造成的回调地狱
    $.get("url", (res1) => {
        conosle.log(res1)
        $.get("url+res1", (res2) => {
            conosle.log(res2)
            $.get("url+res2", (res3) => {
                conosle.log(res3)
                $.get("url+res3", (res4) => {
                    conosle.log(res4)
                })
            })
        })
    })
    

Promise 的特点

  • Promise有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。

    只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态

  • 一旦状态改变,就不会再变,任何时候都可以得到这个结果。

    Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的

二、Promise 用法

ajax 的 Promise 改造

/**
 * 
 * @param {*} data - {type, url, data}
 * @returns 
 */
const ajaxToPromise = (data)=> {
    return new Promise((resolve, reject)=> {
        const xhr = new XMLHttpRequest()
        if (data.type === "get") {
            if(data.data) {
                data.url += "?" + Param(data.data)
            }
            //调用open()方法并采用异步方式
            xhr.open("get", data.url, true);
            //使用send()方法将请求发送出去
            xhr.send();
        } else if (data.type === "post") {
            xhr.open("post", data.url, true);
            xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            xhr.send(Param(data.data))
        }
        xhr.onreadystatechange = function() {
            if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                    resolve(JSON.parse(xhr.responseText));
                } else {
                    reject("Err:" + xhr)
                }
            }
        }
    })
}

Promise.prototype.then() & Promise.prototype.catch()

ajaxToPromise({
    url: 'http://localhost:3007/playerInfo',
    type: 'get',
    data: ''
}).then(res=> {
    console.log(res);
}).catch(err=> {
    console.log(err);
})
  1. then( resolvedCallback , rejectCallback(可选) )
    • 第一个参数接受resolved状态的回调函数,第二个为可选参数,接受rejected状态的回调函数
    • then() 方法返回新的 Promise 对象,所以可以链式调用
  2. catch( rejectCallback )
    • 是 then( null , rejectCallback ) 的别名,但是不建议使用 then 的错误回调方式,因为 Promise 的状态是冒泡的,错误状态将会层层传递,即最后一个 catch 会接受以前所有的错误信息,更加接近于同步写法(try/catch)

      request().then(resolvedCallback).then(resolvedCallback).catch(rejectCallback)
      // Better Than
      request().then(resolvedCallback).then(resolvedCallback, rejectCallback)
      
    • unhandledRejection

Promise.resolve() & Promise.reject()

都是将现有对象转为 Promise 对象,前者是 fulfilled 状态,后者是 rejected 状态

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

Promise.all() & Promise.race()

两者都接收一个具有 Iterator 接口且返回的每个成员都是 Promise 实例的参数,如 Promise 数组

  1. all() 即且函数,当所有 Promise 实例都返回 fulfilled 的状态时才能触发 all 函数的 fulfilled
  2. race() 即或函数,当任一Promise实例为 fulfilled,race 函数就会返回 fulfilled

应用:C 函数必须在互不关联的 A 和 B 执行完后执行

Promise.all([A, B])
.then(res=> { C() })
.catch(err=> console.log(err))

Promise.done() & Promise.finally()

  1. Promise.done(resolvedCallback, rejectedCallback)

    总是存在于链式调用的最后,接收前面所有的报错并向全局抛出

    Promise.prototype.done = function(onFulfilled, onRejected) {
        this.then(onFulfilled, onRejected)
        .catch(function(reason){
            // 抛出全局错误
            setTimeout(()=> {throw reason}, 0)
        })
    }
    
  2. Promise.finally(callback)

    无论前面的 Promise 返回的状态如何,都会执行该 callback

    Promise.prototype.finally = function(callback) {
    		let P = this.constructor
        return this.then(
            value => p.resolve(callback()).then(()=> value),
            reason => P.resolve(callback()).then(()=> {throw reason})
        )
    }
    
posted @ 2024-08-14 07:33  巴伐利亚药水哥  阅读(29)  评论(0)    收藏  举报