Promise

99 阅读4分钟

Promise

定义

  • 是一个构造函数,用于创建Promise实例对象
  • 是一个容器,里面保存着一个尚未完成且预计在未来完成的异步操作
  • 可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数

注意

  • Promise对象的状态只能改变一次
  • 一个Promise对象重点关注它的状态和结果
  • Promise对象如果为失败状态,必须处理,否则报错

1、创建promise

    let res = new Promise((resolve,reject) => {
        //resolve('123')
        //reject('456')
    })
    //默认状态为pending,结果为undefined
  • resolve:是一个函数,pending -> fulfilled
  • reject:是一个函数,pending -> rejected

影响状态改变的因素

  • 返回非Promise值时,为成功状态,结果为return返回的值
  • 返回Promise值时,状态和结果跟随返回的Promise对象
  • 出现异常情况时,为失败状态,结果为报错信息/抛出的值(throw

2、then方法

  • 用于指定Promise对象成功状态和失败状态的回调函数
  • then方法可以传入两个实参(函数),第一个是成功的回调,第二个是失败的回调
  • then方法执行后返回一个新的Promise对象
  • 可以链式调用

终止链式调用

    ele.then(//ele1
        (res1) => {
            console.log('fulfilled...')
        }
        (res2) => {
            console.log('rejected...')
            //原理:返回一个进行中的promise对象  不会执行下一步
            return new Promise(()=>{})
        }
    )//ele2
    .then(
        (res1) => {
            console.log('fulfilled...')
        }
        (res2) => {
            console.log('rejected...')
        }
    )

同步执行

    //1.封装
        function task(ele,time){
            return new Promise((resolve,reject)=>{
                setTimeout(()=>{
                    console.log(ele)
                    resolve('fulfilled...') //变为成功状态
                },time)
            })
        }
  • then //2.then console.log('同步1') task(time1,1500) .then( (res) => { return task(time2,200) } ) .then( (res) => { return task(time3,800) } ) .catch((res) => { console.log('rejected...') }) console.log('同步2')

  • 异步函数:asyncawait

    • async:异步函数
    • await:等待后面Promsie对象成功状态的结果
        //2.await
        (async function(){
            console.log('同步1')
            await task('time1',1200)
            await task('time1',500)
            await task('time1',800)
            console.log('同步2')
        })()
    

自定义Promise

    // 自执行函数  作用域
    (function(){
        function Promise(excutor){
            this.status = 'pending'
            this.result = undefined
            this.callback = []
            let _this = this //缓存this
            /**
            *状态只能改变一次
            *可能性1:先改变状态,再执行 
            *可能性2:先执行,再改变状态 -> 定时器 -> 保存回调函数等待调用
            *reject:失败 错误(console.lag) 抛出(throw)
            */
            function resolve(resolveValue){
                if(_this.status !== 'pending') return //锁定状态
                _this.status = 'fulfilled'
                _this.result = resolveValue
                //遍历callback
                if(_this.callback.length > 0){
                    _this.callback.foreach(item=>{
                        item.resloveCB(resolveValue)
                    })
                }
            }
            function reject(rejectValue){
                if(_this.status !== 'pending') return
                _this.status = 'rejected'
                _this.result = rejectValue
                if(_this.callback.length > 0){
                    _this.callback.foreach(item=>{
                        item.rejectCB(rejectValue)
                    })
                }
            }
            // 捕获错误
            try{
                excutor(resolve,reject)//执行器函数自执行
            }catch(err){
                reject(err)
            }
        }
        Promise.prototype.then = function(){
            /**
            *then 同步执行  回调函数异步执行
            *链式调用 -> 返回new promise
            *跟随上一次的状态和结果
            *返回值:
                *promise对象 -> 判断状态
                *非promose对象
                *报错
            */
            let _this = this
            return new Promise = function(reslove,reject){
                //设置回调函数默认返回值  传参
                resloveCB=typeof resloveCB === 'function'?resloveCB:function(res){return res}
                rejectCB=typeof rejectCB === 'function'?rejectCB:function(res){throw res} 
                //封装trycatch
                function trycatch(callback){
                     //保存上一个的返回值
                        let result  = callback(_this.result)
                        try{
                            if(result instanceof Promise){
                                //跟随上一个的状态和结果 -> then判断状态并执行
                               result.then(reslove,reject)
                               /*result.then(
                                  (res)=>{reslove(res)},
                                  (res)=>{reject(res)}
                                )*/
                            }
                            else{
                                //非promise对象
                                reslove(result)
                            }
                        }catch(err){
                            reject(err) //报错
                        }
                }
                if(_this.status === 'fulfilled'){
                    //异步执行
                    setTimeout(()=>{
                       trycatch(resloveCB)
                    })
                }
                else if(_this.status === 'rejected'){
                     setTimeout(()=>{
                        trycatch(rejectCB)
                    })
                }
                else if(_this.status === 'pending'){
                    /**
                    *先调用再改变状态
                    *多个then调用 多个回调函数 -> 数组对象
                    *保存回调函数等待调用
                    */
                    _this.callback.push({
                        'resloveCB':function(){
                            trycatch(resloveCB)
                        }
                        'rejectCB':function(){
                            trycatch(resloveCB)
                        }
                    })
                }
            }
        }
        /**
        *then 没有失败的回调函数
        *catch 需要设置成功的回调函数默认值
        *catch 返回promise对象
        */
        Promise.prototype.catch = function(catchCB){
            //成功的回调为null
            return this.then(null,catchCB)
        }
        //静态方法
        /**
        *resolve 返回promise对象
        *非promise对象 返回resolve
        *promise对象 由对象的状态和结果决定
        */
        Promise.resolve = function(value){
            return new Promise((reslove,reject)=>{
                if(value instanceof Promise){
                    value.then(reslove,reject)
                }else{
                    reslove(value)
                }
            })
        }
        /**
        *all 数组内所有成功返回reslove,则返回promise对象
        *失败则返回第一个失败值
        *传值与返值顺序一致 -> index
        */
        Promise.all =function(arr){
            return new Promise(reslove,reject)=>{
                let results = [] //成功的数组
                let count = 0 //成功的个数
                arr.foreach((item,index)=>{
                    //Promise.reslove包装成promise对象
                    Promise.reslove(item).then(
                        (res)=>{
                            count++
                            results[index] = res
                            if(arr.length === count) reslove(results)
                        },
                        (res)=>{reject(res)}
                    )
                }
            }
        }
        //对外暴露
        window.Promise = Promise
    })()

用promise写一个路由

    const routes = {
        '/':home,
        '/a":'a',
        '/b':'b'
    }
    function router(path){
        return new Promise((resolve,reject)=>{
            if(routes[path]){
                resolve(routes[path])
            }
            else{
                reject('不存在')
            }
        })
    }
    router('/')
    .then(res=>console.log(res))
    .catch(err=>console.log(err))

promise封装ajax

    function ajax(method,url,data){
        return new Promise((resolve,reject)=>{
            let xhr = new XMLHttpRquest()
            xhr.open(method,url)
            if(method === 'post'){
                xhr.setRequestHeader('content-type','application/json;charset=utf-8')
            }
            xhr.onload = function(){
                if(xhr.status>=200&&xhr.status<300){
                    resolve(xhr.response)
                }
                els{
                    reject({
                        status:this.status,
                        statusText:xhr.statusText
                    })
                }
            }
           xhr.onerror = function(){
               reject({
                        status:this.status,
                        statusText:xhr.statusText
                    })
                   }
                })
          if(method === 'post'){
              xhr.send(JSON.stringify(data))
          }
          els if(method === 'get'){
              xhr.send(data)
          }
    }