promise详解

Posted wlhappy92

tags:

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

1、promise

1.1、为什么用promise

主要为了解决回调地狱的问题

异步结构不清晰,promise可以让异步操作结构变得很清晰

1.2、promise语法

executor是带有 resolvereject 两个参数的函数 。Promise构造函数执行时立即调用executor 函数, resolvereject 两个函数作为参数传递给executor(executor 函数在Promise构造函数返回所建promise实例对象前被调用)。resolvereject 函数被调用时,分别将promise的状态改为fulfilled(完成)或rejected(失败)。executor 内部通常会执行一些异步操作,一旦异步操作执行完毕(可能成功/失败),要么调用resolve函数来将promise状态改成fulfilled,要么调用reject 函数将promise的状态改为rejected。如果在executor函数中抛出一个错误,那么该promise 状态为rejected。executor函数的返回值被忽略。

简单理解上面一段话,new Promise()里面接收一个函数,这个函数会理解执行,函数里面有两个参数resolve和reject,函数的执行体里面是异步的操作,异步操作有成功有失败

  • 成功:状态pending->fulfilled,并且用resolve 去接收成功的值
  • 失败:状态pending->rejected,并且用reject 去接收失败的值
  • 3种状态两种结果
new Promise( function(resolve, reject) {...} /* executor */  );

简单例子

 let p1=new Promise(function(resolve,reject){
           setTimeout(function(){
               let num=new Date().getTime();
               num%2==0?resolve('成功'):resolve('失败')
           },0)
        })
        p1.then(function(value){
            console.log(value)
        },function(reason){
            console.log(reason)
        })

连写

 let p1=new Promise(function(resolve,reject){
           setTimeout(function(){
               let num=new Date().getTime();
               num%2==0?resolve('成功'):resolve('失败')
           },0)
        }).then(function(value){
            console.log(value)
        },function(reason){
            console.log(reason)
        })

如果一个promise即调用了resolve,又调用了reject,谁先调用,最后就走对应的方法,

 new Promise(function (resolve, reject) {
            resolve("成功")
            reject("失败")
            console.log("执行了")
        }).then(value => {
            console.log(value)
        }, reason => {
            console.log(reason)
        })
        // 执行了
        // 成功

如果没有成功,刚在then的第二个参数写的失败的回调函数,其实也可以用catch

 new Promise(function (resolve, reject) {
           reject("失败")
            resolve("成功")
        })
        .then(value => {
            console.log(value)
        })
        .catch(reason => {
            console.log(reason)
        })
        // 失败

1.3、Promise.resolve()

成功的语法糖

let p1=new Promise(function(resolve,reject){
            resolve(11)
        })
        p1.then(function(value){
            console.log(value)
        })

Promise.resolve()

const p1=Promise.resolve(11); //跟上面是一样的
p2.then(value=>{console.log(value)})

1.4、Promise.reject()

失败的语法糖

const p3=Promise.reject(33)
p2.then(null,reason=>{console.log(reason)})

1.5、Promise.All()

Promise.All():发送了多个请求,只有全部成功才走成功的处理,只要其中有一个失败就失败,这个返回的是p2的原因

  • 失败原因,走第一个失败的原因
 const p1 = Promise.resolve(11); //跟上面是一样的
        const p2 = Promise.reject(22)
        const p3 = Promise.reject(33)
    
        const pAll = Promise.all([p1, p2, p3])
        pAll.then(
            value => {},
            reason => {
                console.log(reason)
            }
        )
  • 成功是几个结果组成的数组,结果顺序跟[p1, p2, p3]一样
 const p1 = Promise.resolve(11); //跟上面是一样的
        const p2 = Promise.resolve(22)
        const p3 = Promise.resolve(33)
    
        const pAll = Promise.all([p1, p2, p3])
        pAll.then(
            values => {
                console.log(values)
            }
        )
//[11,22,33]

1.6、Promise.race()

多个异步任务,谁先执行完就用谁的,可以用setTimeout延迟去模拟,这里我就不试了

const p1 = Promise.resolve(11); //跟上面是一样的
        const p2 = Promise.resolve(22)
        const p3 = Promise.resolve(33)
    
        const pRace = Promise.race([p1, p2, p3])
        pRace.then(
            value => {
                console.log(value)
            }
        )

如果第一个执行完是一个失败的,那就走失败

 const p1 = Promise.reject(11); //跟上面是一样的
        const p2 = Promise.resolve(22)
        const p3 = Promise.resolve(33)
    
        const pRace = Promise.race([ p1,p2, p3])
        pRace.then(
            value => {
                console.log(value)
            },
            reason=>{
                console.log(reason)
            }
        )

1.7、promise理解

1、如何改变promise的状态?
    resolve(value): 如果当前是pendding就会变为resolved
    reject(reason): 如果当前是pendding就会变为rejected
    抛出异常: 如果当前是pendding就会变为rejected
//如果当前是pendding就会变为rejected,内部抛出也是这样
const p=new Promise((resolve,reject)=>{
  throw new Error('出错了')
})

const p = new Promise((resolve, reject) =>{
        //resolve(1)//promies变为resolved成功状态
        //reject(2)//promise变为rejected失败状态
        //throw new Error("出错了")//抛出异常promise变为rejected失败状态,reason 为抛出的error
        throw 3
    });
    p.then(
        reason => {console.log("reason:", reason)}//3
    )
2、一个promise指定多个成功/失败回调函数,都会调用吗?
    都会调用
 const p1=Promise.resolve('11')
        p1.then(value=>{
            console.log("第一次"+value)
        })
        p1.then(value=>{
            console.log("第二次"+value)
        })
        //第一次11
        //第二次11
3、改变promise状态和指定回调函数谁先谁后
   3.1、都有可能,正常情况下时先指定回调函数再改变状态,但也可以先改变状态再指定回调函数
   3.2、如何先改变状态再指定回调?
     3.2.1、在执行器中直接调用resolve()/reject()
     3.2.2、延迟更长时间才调用then()
new Promise((resolve, reject) =>{
        setTimeout(()=>{
            resolve(1)//后改变的状态(同时指定数据),异步执行回调函数
        }, 1000)    
    }).then(//先指定回调函数,保存当前指定的回调函数
        value => {console.log("value1:", value)}//value1: 1
    )
4、promise.then()返回的新的promise的结果状态由什么决定?
  4.1、简单表达:由then()指定的回调函数执行的结果决定
  4.2、详细表达:
    4.2.1、如果抛出异常,新promise变为rejected,reason为抛出的异常
    4.2.2、如果返回的是非promise的任意值,新的promise变为resolved,value为返回的值
    4.2.3、如果返回的是另一个新promise,此promise的结果就会成为新promise的结果 
new Promise((resolve,reject)=>{
            setTimeout(function(){
                resolve(11)
            },1000)
        })
        .then(value=>{
            console.log("第一次"+value)
        })
        .then(value=>{
            console.log("第二次"+value)
        })
        //第一次11
        //第二次undefined
 new Promise((resolve,reject)=>{
            setTimeout(function(){
                reject(11)
            },1000)
        })
        .then(value=>{
            console.log("成功第一次"+value)
        },reason=>{
         console.log("失败第一次"+reason)
        })
        .then(value=>{
            console.log("成功第二次"+value)
        },reason=>{
         console.log("失败第二次"+reason)
        })
        //失败第一次11
        // 成功第二次undefined

以下都是针对第二次then的结果

new Promise((resolve,reject)=>{
            setTimeout(function(){
                resolve(11)
            },1000)
        })
        .then(value=>{
            console.log("成功第一次"+value)
            // return 2  //成功第二次2
            // return Promise.resolve(2)  //成功第二次2
            // return Promise.reject(2)  //失败第二次2
            throw 3;  //失败第二次3



        },reason=>{
         console.log("失败第一次"+reason)
        })
        .then(value=>{
            console.log("成功第二次"+value)
        },reason=>{
         console.log("失败第二次"+reason)
        })

3、参考链接

MDN promise

MDN promise使用

promise详解

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

前端面试题之手写promise

深入 Promise——Promise 实现详解

js promise详解

澄清 node.js + promises 片段

promise用法详解

ES6 Promise 详解