一、Promise(承诺)

1.什么是promise

一个 Promise 对象代表一个在这个 promise 被创建出来时不一定已知值的代理。它让你能够把异步操作最终的成功返回值或者失败原因和相应的处理程序关联起来。这样使得异步方法可以像同步方法那样返回值:异步方法并不会立即返回最终的值,而是会返回一个 promise,以便在未来某个时候把值交给使用者。

2.promise用来做什么的?

异步编程的一种解决方案

                                                    

二、promise基本认知

1.promise其实就是一个构造函数:

new Promise((resolve,reject)=>{
        resolve(1)
        reject(1)
})

其中的resolvereject是两个形参,resolve代表成功,reject代表失败。

2.promise有三个状态

  • 待定(pending): 初始状态,既没有被兑现,也没有被拒绝。
  • 已兑现(fulfilled): 意味着操作成功完成。
  • 已拒绝(rejected): 意味着操作失败。

3.例如:用延时器settimeout模拟一个Ajax,我这里定义了一个变量fn,然后直接打印fn。

let fn = new Promise((resolve,reject)=>{
        setTimeout(() => {
            resolve(1)
        }, 1000);
})
    console.log(fn)

结果:

 代码执行如下:

状态由pending变为fulfilled,这就是成功的过程

promisestate:承诺状态

promiseresult:承诺结果

然后调用reject看看如下结果:

let fn = new Promise((resolve,reject)=>{
        setTimeout(() => {
            reject(1)
        }, 1000);
})
    console.log(fn)

结果:

 

代码执行:

状态由pending变为rejected,这就是成功的过程

 4.这里偷老师(csdn搜索:奥特曼)一个图让同学们能够更加直观的明白promise三个状态:

小结 

最初创建对象的状态是pending     当调用了 resolve方法时 就会进入 fulfilled 状态,当调用reject方法,就会进入 rejected 状态,当状态一旦发送改变 就不会重新改变。

                                                            

三、PromiseResult

2.1 在上面的打印中,可以看到PromiseResult和PromiseState,PromiseState上面有介绍,这里就不再解释了,说一下PromiseResult。翻译就是:承诺结果。PromiseResult的值(值可以是任意数据类型,其实就是resolve和rejected传入的参数。

那么问题来了,这么拿到PromiseResult里面的值呢?

在then和catch方法中它的参数是一个回调函数,在这个回调函数中的参数中就可以拿到resolve传过来的值,也就是promiseValue。

new Promise((resolve,reject)=>{
        setTimeout(() => {
            resolve(1)
            reject(1)
        }, 1000);
})
.then(res=>console.log(res+'成功就会执行'))
.catch(res=>console.log(res+'失败就会执行'))
.finally(()=>console.log('成功或失败都执行'))

当调用resolve函数时传递的参数,会由.then回调函数的参数接收,状态pending----fulfilled

当调用reject函数时传递的参数,会由.catch回调函数的参数接收,状态pending----fulfilled

2.2   .then的参数有两个,而且.then返回的任然是一个新的promise。

// then中有两个参数,第二个参数是可选的
new Promise((resolve,reject)=>{
        reject(1)
}).then((res)=>{console.log(res+'成功就会执行')},
(err)=>{console.log(err+'失败就会执行')})

结果:

 如果你不去接收reject的时候就会报错,显示:

 

 ok,书接上文。

 四、promise链式调用

链式调用,顾名思义,一个接着一个,像链条一样相互连接。

上面有说.then返回的仍是一个promise对象:

 let fn = new Promise((resolve,reject)=>{
            resolve(1)
        })
        let fn1 = fn.then((res)=>{})
        console.log(fn1)

结果:

 因为返回值仍是新的promise,那么就可以开始链式调用了

    let num = new Promise((resolve, rejected) => {
            resolve(1)
        })
        let num1 = p1.then((res) => {
           console.log(res); 
           return 2
        })
        num1.then((res)=>{
           console.log(res); 
        })

结果:我这里只写了.then,你可以多写点~~~

五、回调地狱

                                                             

本来就够难了,这咋还来个地狱呢,听着挺吓人。不过不要害pia~

回调地狱就是,异步代码中使用函数回调变得模糊或难以遵循的任何代码,说白了就是代码嵌套多层,可读性差,出现问题难以解决。然而promise就是可以完美解决这种问题的工具。

1.模拟ajax 回调地狱 每次调用setTimeout 都是拿到上一次的值-1

        function fn1(a) {
            setTimeout(() => {
                console.log(a);
                a--;
                setTimeout(() => {
                    console.log(a);
                    a--
                    setTimeout(() => {
                        console.log(a);
                        a--
                        setTimeout(() => {
                            console.log(a);
                            a--
                            setTimeout(() => {
                                console.log(a);
                            }, 1000);
                        }, 1000);
                    }, 1000);
                }, 1000);
            }, 1000);
        }
        fn1(5)

 使用promise

    function fn1(a) {
          new Promise((res,rej)=>{
                res(a)
            })
            .then((params)=>{
              return  new Promise((res,rej)=>{
                setTimeout(() => {  console.log(params);res(--params) }, 1000) }) 
             })
             .then((params)=>{
              return  new Promise((res,rej)=>{
                setTimeout(() => {  console.log(params);res(--params) }, 1000) }) 
             })
             .then((params)=>{
              return  new Promise((res,rej)=>{
                setTimeout(() => {  console.log(params);res(--params) }, 1000) }) 
             })
             .then((params)=>{
              return  new Promise((res,rej)=>{
                setTimeout(() => {  console.log(params);res(--params) }, 1000) }) 
             })
             .then((params)=>{
              return  new Promise((res,rej)=>{
                setTimeout(() => {  console.log(params);res(--params) }, 1000) }) 
             })        
         }
         let a=5
         fn1(a)

六、Promise.all()的使用

解释:Promise.all()方法用于将多个Promise实例,包装成一个新的Promise实例。

let promise1= new Promise((resolve, reject) => {
  resolve('promise1成功')
})

let promise2 = new Promise((resolve, reject) => {
  resolve('promise2成功')
})

let promise3= Promise.reject('promise3失败')


// Promise.all内有一个失败就会返回失败在.catch查看,反之会返回成功值在.then中查看
Promise.all([promise1, promise2 , promise3]).then((result) => {
  // result的值是个数组[]
  console.log('成功执行', result)               
}).catch((error) => {
  console.log('失败执行',error)
}).finally(()=>{
    console.log('成功或失败都会执行')
})

常见用途:需要多个接口有返回值以后再去调用其他接口,这个时候使用promise.all()非常实用。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐