Promise相关概念

Posted 活到老学到老的李小小

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Promise相关概念相关的知识,希望对你有一定的参考价值。

一、关于promise


1. 处理异步操作
2. 是一个构造函数,可实例化
3. 支持链式调用,解决回调地狱问题


二、 promise初使用


const
p = new Promise((resolve,reject) => {   setTimeout(()=>{     let n = rand(1,100) //获取1-100随机数     if(n <=30)       resolve(n); //将promise对象状态设置为成功,n作为成功的值传入     else       reject(n);// 设置为失败,n作为失败的值   },1000) }) //调用then方法 then(fun1(),fun2()) //then方法的参数为两个函数,一个成功时处理函数,一个失败时处理函数 p.then((value) =>{ console.log(\'成功\') //成功时的处理,value为成功值 },(reason)=>{ console.log(\'失败\') //失败时的处理,reason为失败值 })
// promise---fs文件读取
cosnt fs = require(\'fs\')
let p = new Promise((reslove.reject)=>{
  fs.readFile(\'./file1/content.txt\',(err,data)=>{
  if(err)    reject(err);
  resolve(data);
 })
})
p.then((value)=>{console.log(value.toString)},(reason)={console.log(reason)})

// promise---发送Ajax
const p = new Promise((resolve,reject)=>{
  const xhr = new XMLHttpRequest() //创建
  xhr.open(\'GET\',\'https://api.apiopen.top/getJoke\')//初始化
  xhr.send()
  xhr.onreadystatechange = function(){
    if(xhr.readyState === 4){
      if(xhr.status >=200 && xhr.status <= 300){
        resolve(xhr.response)
       }else{
         reject(xhr.status)
        }
    }
  }
})

p.then((value)=>{
  cosole.log(value)
},(reason)=>{
  console.log(reason)
})

// util.promisify 该方法可转化为promise对象的封装函数

    const util = require(\'until\')
    const fs = require(\'fs\')
    let myReadfile = until.promisify(fs.readFile)
    myReadfile(\'./file1/content.txt\').then(value=>{
        ....//成功的执行函数
    })
    
// 封装promise ---ajax
        
    function sendAjax(url){
        return new Promise((resolve,reject){
            const xhr = new XMLHttpRequest()
            xhr.open(\'GET\',url)
            xhr.send()
            xhr.onreadystatechange = functionz(){
                if(xhr.readyState === 4){
                    if(xhr.status >=200 && xhr.status< 300){
                        resolve(xhr.response)
                    }else{
                        reject(xhr.status)
                    }
                }
            }
        })
    }
    
    sendAjax(\'https://api.apiopen.top/getJoke\')
    sendAjax.then((value)=>{},(reason)=>{})

1. 执行器函数
Promise((excutor)=>{})
(reslove,reject)=>{}
说明:excecutor会在Promise内部立即同步调用,而异步操作在执行器中执行

2. catch方法
专门指定失败的回调


3. promise.resolve/reject
  1).promise的属性状态值:PromiseState:\'pending\'/\'rejected\'/\'resloved\'
        属性结果值: PromiseResult:
  2).resolve/reject是promise的api方法
    resolve:let r = Promise.resolve()
        如果传入非promise对象则都返回成功的promise对象
        如果传入promise对象 ,则返回值为这个传入的promise所确定的成功或失败值
    reject:let r = Promise.reject()
        无论传入任何值都是失败的,传入什么失败的值就是什么
4. Promise.all
  1).该方法的参数为Promise对象组成的数组
  2).如果数组里所有的Promise对象都成功,则返回成功promise对象,其结果值为成功的值组成的数组
  3).若有Promise对象失败,则返回第一个失败promise对象的失败值

5. Promise.race
  1).与上面方法同样是传入promise数组
  2).返回值由数组中那个最先被执行的promise对象
6.改变promise对象状态方式
  1).resolve(\'success\') 由pending => fulfilled(resloved)
  2).reject(\'error\') 由pending => rejected
  3).抛出错误:throw \'error

 

三、 一些关键问题
  1.一个promise指定多个成功/失败回调函数,都会调用吗?
   当promise改变对应状态时都会调用,所以只有在状态改变时才会执行该类回调
  2.then方法返回的是一个promise对象,其状态值为回调函数的返回值,

   如果返回值为promise对象,它的状态值就是then返回的promise状态值

  3.链式调用和异常穿透:当通过链式调用时,如果需要处理其中的失败,直接在最后catch方法处理
   4.如何中断promise链:从其中的某个链中返回pending状态的promise

四、自定义封装promise函数

 

class Promise {
    constructor(executor) {
        this.PromiseState = \'pending\'
        this.PromiseResult = null
        this.callback = [] //then的参数值容器
        const that = this

        function resolve(data) {
            //保证状态值只能改一次
            if (that.PromiseState !== \'pending\') return
            //设置状态值为成功
            that.PromiseState = \'fullfilled\'
            //设置promise结果值
            that.PromiseResult = data
            //实现链式调用
            setTimeout(() => {
                that.callback.forEach(item => {
                    item.onResolve(data)
                })
            })
        }

        function reject(data) {
            if (that.PromiseState !== \'pending\') return
            //设置状态值为失败
            that.PromiseState = \'rejected\'
            //设置promise结果值
            that.PromiseResult = data
            setTimeout(() => {
                that.callback.forEach(item => {
                    item.onReject(data)
                })
            })
        }
        //设置通过throw 改变状态值
        try {
            //立即执行保证同步调用(执行器函数)
            executor(resolve, reject);
        } catch (e) {
            reject(e) //e为throw ‘error’ 抛出异常时的值
        }
    }

    //指定原型then方法
    then(onResolve, onReject) {
        const that = this
        //判断回调函数参数 设置参数默认值
        if (typeof onReject !== \'function\') {
            onReject = reason => {
                throw reason
            }
        }
        if (typeof onResolve !== \'function\') {
            onResolve = value => value
        }

        return new Promise((resolve, reject) => {
            //封装重复函数
            function callback(type) {
                try {
                    let result = type(that.PromiseResult)
                    if (result instanceof Promise) {
                        //if返回对象为promise
                        result.then(v => {
                            resolve(v)
                        }, r => {
                            reject(r)
                        })
                    } else {
                        //设置返回值的promise对象成功值
                        resolve(result)
                    }
                } catch (e) {
                    reject(e) //当抛出异常
                }
            }
            //console.log(this)// 运用箭头函数的原因 这里的this指向函数定义的代码块
            //设置成功的回调执行
            if (this.PromiseState === \'fullfilled\') {
                //保证then方法内回调为异步执行
                setTimeout(() => {
                    callback(onResolve)
                })
            }
            //设置失败回调执行
            if (this.PromiseState === \'rejected\') {
                setTimeout(() => {
                    callback(onReject)
                })
            }
            //设置改变状态后再执行then回调(对于回调方式改变状态值)
            if (this.PromiseState === \'pending\') {

                this.callback.push({
                    onResolve: function() { //处理promise异步修改对象状态(实现then回调函数执行在异步回调之后)
                        callback(onResolve)
                    },
                    onReject: function() {
                        callback(onReject)
                    }
                })
            }

        })
    }

    //添加catch方法
    catch (onreject) {
        return this.then(undefined, onreject)
    }

    //给构造函数promise封装resolve 和reject方法
    static resolve(value) {
        return new Promise((resolve, reject) => {
            if (value instanceof Promise) {
                value.then(v => {
                    resolve(v)
                }, r => {
                    reject(r)
                })
            } else {
                resolve(value)
            }
        })
    }
    static reject(reason) {
        return new Promise((resolve, reject) => {
            reject(reason)
        })
    }

    //封装all方法
    static all(values) {
        return new Promise((resolve, reject) => {
            let count = 0
            let arr = []
            for (let i = 0; i < values.length; i++) {
                values[i].then(v => {
                    count++
                    arr[i] = v
                    if (count === values.length) {
                        resolve(arr)
                    }
                }, r => {
                    reject(r)
                })
            }
        })
    }

    //封装race方法
    static race(values) {
        return new Promise((resolve, reject) => {
            for (let i = 0; i < values.length; i++) {
                values[i].then(v => {
                    resolve(v)
                }, r => {
                    reject(r)
                })
            }
        })
    }

}

 

五、 async 函数与 await表达式

    1. async用法与then方法类似
        1).返回非promise类型数据 则该函数返回值为成功promise,且promiseResult为返回对象
        2)返回promise对象,函数返回值promise--promiseResult,promiseState由返回promise决定
        
async function fun(){
       return 123;
   }
 let res = fun()// promiseResult :123

 

 
    2.await 只能async中使用
        1).如果await右侧为成功promise ,则直接返回对应的promiseResult
        2).如果是失败的promise对象,抛出错误,可用try catch捕获
        3).右侧为其他类型数据,是什么就返回什么
        
        
async function fun(){
         let p = new Promise((resolve,reject)=>{
         resolve(\'ok\')
    })
    let res = await p
    console.log(res) // ok
}

 

        

以上是关于Promise相关概念的主要内容,如果未能解决你的问题,请参考以下文章

Promise相关概念

前端面试题之手写promise

浏览器事件循环相关概念及其理解

[转]JS - Promise使用详解1(基本概念使用优点)

从源码看 Promise 概念与实现

JS - Promise使用随笔