学习笔记 Promise详解

162 阅读5分钟

为什么要用Promise?

1. 指定回调函数的方式更加灵活:

旧的: 必须在启动异步任务前指定promise: 启动异步任务 => 返回promie对象 => 
给promise对象绑定回调函数(甚至可以在异步任务结束后指定)

2. 支持链式调用, 可以解决回调地狱问题什么是回调地狱? 回调函数嵌套调用,
外部回调函数异步执行的结果是嵌套的回调函数执行的条件回调地狱的缺点? 
不便于阅读 / 不便于异常处理解决方案? promise链式调用终极解决方案? async/await


1.Promise构造函数

Promise (excutor) {}excutor函数: 同步执行 (resolve, reject) => {}resolve函数: 内部定义成功时我们调用的函数 value => {}reject函数: 内部定义失败时我们调用的函数 reason => {}

说明: excutor会在Promise内部立即同步回调,异步操作在执行器中执行

2. Promise.prototype.then方法:

 (onResolved, onRejected) => {}

 onResolved函数: 成功的回调函数 (value) => {} onRejected函数: 失败的回调函数 (reason) => {}

说明: 指定用于得到成功value的成功回调和用于得到失败reason的失败回调返回一个新的promise对象

3. Promise.prototype.catch方法: 

(onRejected) => {}onRejected函数: 失败的回调函数 (reason) => {}

说明: then()的语法糖, 相当于: then(undefined, onRejected)

4. Promise.resolve方法: 

(value) => {}value: 成功的数据或promise对象

说明: 返回一个成功/失败的promise对象

5. Promise.reject方法: 

(reason) => {}reason: 失败的原因

说明: 返回一个失败的promise对象

6. Promise.all方法: 

(promises) => {}promises: 包含n个promise的数组

说明: 返回一个新的promise, 只有所有的promise都成功才成功, 只要有一个失败了就直接失败
7. Promise.race方法:

 (promises) => {}promises: 包含n个promise的数组

说明: 返回一个新的promise, 第一个完成的promise的结果状态就是最终的结果状态

promise的几个关键问题1:如何改变promise的状态

(1)resolve(value): 如果当前是pendding就会变为resolved
(2)reject(reason): 如果当前是pendding就会变为rejected
(3)抛出异常: 如果当前是pendding就会变为rejected

promise的几个关键问题2:一个promise指定多个成功/失败回调函数, 都会调用吗?promise的几个关键问题3:改变promise状态和指定回调函数谁先谁后?

(1)都有可能, 正常情况下是先指定回调再改变状态, 但也可以先改状态再指定回调
(2)如何先改状态再指定回调?
①在执行器中直接调用resolve()/reject()
②延迟更长时间才调用then()
(3)什么时候才能得到数据?
①如果先指定的回调, 那当状态发生改变时, 回调函数就会调用, 得到数据
②如果先改变的状态, 那当指定回调时, 回调函数就会调用, 得到数据
 常规: 先指定回调函数, 后改变的状态

    new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(1) // 后改变的状态(同时指定数据), 异步执行回调函数
      }, 1000);
    }).then( // 先指定回调函数, 保存当前指定的回调函数
      value => {},
      reason => { 
       console.log('reason', reason)
      } 
   ) 
   // 如何先改状态, 后指定回调函数 
   new Promise((resolve, reject) => {
      resolve(1) // 先改变的状态(同时指定数据)
    }).then( // 后指定回调函数, 异步执行回调函数 
     value => {
        console.log('value2', value) 
     },
      reason => { 
       console.log('reason2', reason) 
     } 
   ) 
   console.log('-------') 
   const p = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(1) // 后改变的状态(同时指定数据), 异步执行回调函数
      }, 1000);
    }) 
   setTimeout(() => { 
     p.then(
        value => { 
         console.log('value3', value) 
       }, 
       reason => {  
        console.log('reason3', reason) 
       } 
     ) 
   }, 1100);

promise的几个关键问题4:promise.then()返回的新promise的结果状态由什么决定?

(1)简单表达: 由then()指定的回调函数执行的结果决定
(2)详细表达:
①如果抛出异常, 新promise变为rejected, reason为抛出的异常
②如果返回的是非promise的任意值, 新promise变为resolved, value为返回的值
③如果返回的是另一个新promise, 此promise的结果就会成为新promise的结果 

new Promise((resolve, reject) => {
      // resolve(1)     
 reject(1)    
}).then(  
    value => {  
      console.log('onResolved1()', value)  
      // return 2      
      // return Promise.resolve(3)  
      // return Promise.reject(4)   
     throw 5    
  },    
  reason => {    
    console.log('onRejected1()', reason)  
      // return 2    
    // return Promise.resolve(3)    
    // return Promise.reject(4)   
     throw 5   
   }  
  ).then(  
    value => {    
    console.log('onResolved2()', value)  
    },   
   reason => {   
     console.log('onRejected2()', reason)  
    }   
 )

promise的几个关键问题5:promise.then()返回的新promise的结果状态由什么决定?

(1)promise的then()返回一个新的promise, 可以开成then()的链式调用
(2)通过then的链式调用串连多个同步/异步任务

 new Promise((resolve, reject) => {   
   setTimeout(() => {     
   console.log("执行任务1(异步)")     
   resolve(1)   
   }, 1000);   
 }).then(   
   value => {     
   console.log('任务1的结果: ', value)    
   console.log('执行任务2(同步)')     
   return 2    
  }   
 ).then(  
    value => {   
     console.log('任务2的结果:', value)         
       return new Promise((resolve, reject) => {     
     // 启动任务3(异步)      
    setTimeout(() => {     
       console.log('执行任务3(异步))')   
         resolve(3)  
        }, 1000);   
     })  
    }  
  ).then( 
     value => {  
      console.log('任务3的结果: ', value) 
     } 
   )

promise的几个关键问题6:promise异常传/穿透?

(1)当使用promise的then链式调用时, 可以在最后指定失败的回调,
(2)前面任何操作出了异常, 都会传到最后失败的回调中处理

promise的几个关键问题7:中断promise链?

(1)当使用promise的then链式调用时, 在中间中断, 不再调用后面的回调函数
(2)办法: 在回调函数中返回一个pendding状态的promise对象

   
new Promise((resolve, reject) => {     
 // resolve(1)   
  reject(1)  
  }).then( 
     value => {  
      console.log('onResolved1()', value)    
    return 2      },     
 // reason => {throw reason}   
 ).then(   
   value => {    
    console.log('onResolved2()', value)   
     return 3      },   
   reason => {throw reason}  
  ).then(   
   value => {    
    console.log('onResolved3()', value)   
   },  
    reason => Promise.reject(reason)   
 ).catch(reason => {   
   console.log('onReejected1()', reason)   
   // throw reason     
  // return Promise.reject(reason)    
  return new Promise(() => {}) // 返回一个pending的promise  中断promise链  
  }).then(    
  value => {     
   console.log('onResolved3()', value)   
   },     
 reason => {    
    console.log('onReejected2()', reason)  
    } 
   )