Promise 浅析

227 阅读4分钟
promise 是es6引入的进行异步编程的新解决方案
旧的:旧方案是淡村的使用回调函数,如下面的各种情况

什么是异步编程:

  • fs文件操作
  • 数据库操作
  • ajax数据请求
  • 定时器
//1.Promise封装fs读取文件
let fs = require('fs');
//封装一个函数使用promise的方式读取文件

function mainfs(path){
  return new Promise((resolve,reject)=>{
    fs.readFile(path,(err,data)=>{
      if(err) reject(err);
      resolve(data)
    })
  });
}

mainfs('./text.txt').then(res=>{
  console.log(res.toString(),'111');
}),res=>{
  console.log(res,'222');
};

//2.Promise封装AJAX请求
  function sendAJAX(url){
    return new Promise((resolve,reject)=>{
      let xhr = new XMLHttpRequest();
      xhr.responseType = 'json';
      xhr.open('GET',url)
      xhr.send();
      xhr.onreadystatechange = function(){
        if(xhr.readyState === 4){
          if(xhr.status >= 200 && xhr.status < 300){
            resolve(xhr.response)
          }else{
            reject(xhr.status)
          }
        }
      }
    });
  }
  sendAJAX('https://api.imjad.cn/cloudmusic/?type=song&id=28012031').then(value=>{
    console.log(value,'111');
  },res=>{
    console.log(res,'222');
  });

promise 的优点:

  • 支持链式调用可以解决回调地狱的问题,代码不断的向下递进(代码不已阅读,不便于异常处理).
  • 指定回调函数的方式更加的灵活.(给promise对象绑定回调函数,甚至可以绑定多个函数)

Promise属性

1.PromiseStatus
Promise 状态的改变(PromiseStatus状态是Promise实例中的一个属性):
    pending  可以变为resolve
    pending  可以变为reject
有三种状态(pending,resolve,reject),但是只有两种转化过程(pending->resolve,peding->reject),
说明一个Promise最终只有两种改变状态,一个是pending到成功,一个pending到失败,
最终都会有一个结果,并且一个Promise的状态只可以改变一次,
2.PromiseResult
Promise 对象的值(PromiseResult保存的是异步任务的结果):
成功 resolve
失败 reject
Promise状态的改变的方式(有三种)
 let p = new Promise((resolve,reject)=>{
     //当前状态 pending
    // resolve('ok') //1.pending(进行中) - fulfilled(成功) 
    // reject('error') //2.pending(进行中) - rejected(失败)
    // throw '失败了' //3.pending(进行中) - rejected(失败)
  })
  console.log(p);
Promise 相关API
// 1 Promise构造函数 Promise(executor){}
(1)executor 执行器函数 (resolve,reject)=>{}
    (1.1)resolve 定义内部成功执行的函数
    (1.2)reject 定义内部失败执行的函数
执行器函数会在Promise 内部立即执行,异步操作在执行器中执行( Promise一旦创建立即执行 )

//2 Promise.prototype.then(onResolveed,onRejected)=>{};(Promise的实例对象)
(1)onResolveed:成功的回调
(2)onRejected:失败的回调

//3 Promise.prototype.catch(onRejected)=>{}; 
(1)onRejected:失败的回调

//举例
let p = new Promise((resolve,reject)=>{
    // resolve('ok')
    reject('error')
    // throw '失败了'
  })
  // p.then(value=>{
  //   console.log(value);//ok
  // },reason=>{
  //   console.log(reason);
  // })
  p.catch(res=>{
    console.log(res);//error
  })
  
  
  //4 Promise.resolve(value)
  (1)value:成功的数据或者是Promise对象;//说明:返回一个成功或者是失败的Promise对象
   let p = Promise.resolve('ok11')
   console.log(p);//Promise {<fulfilled>: 'ok11'}
   注意:1.如果传递的参数为非Promise类型的对象,则返回的结果为成功的Promise 对象,参数的结果决定了Promise对象的resolve的结果
   非Promise 类型的数据: string,number,boolean,undefined, null,[],{},
   2.如果传入的参数是Promise对象,  Promise 的结果有参数的结果决定
     let p = Promise.resolve(new Promise((resolve,reject) => {
        reject('error')
        //reject('ok')
      }))
      console.log(p);//error / ok ,两种情况成功或者失败
      
  //5 Promise.reject(value)
  (1)任何数据或者是一个Promise对象;返回的结果一直是一个失败的Promise对象
  let p = Promise.reject(123)
  console.log(p);//Promise {<rejected>: '123'} //非Promise 类型的数据: string,number,boolean,undefined, null,[],{},
  (2) 也可以是一个Promise对象,但是结果还是rejected的,result 是一个Promise类型的数据.
     let p = Promise.reject(new Promise((resolve,reject) => {
        resolve('ok')
      }))
      console.log(p);//Promise {<rejected>: Promise}
      
   //6 Promise.all(value); value一般为一个Promise对象 组成的数组,返回的结果也是一个Promise对象.
   返回的结果为Promise 数组都成功的值得数组,如果其中有一个失败了就返回这个失败的值
  let p1 = Promise.resolve('1111')
  let p2 = Promise.resolve('2222')
  let p3 = Promise.resolve('3333')
  let p4 = Promise.reject('4444')
  let p = Promise.all([p1,p2,p3]);
  console.log(p);//fulfilled->Array(3)
  let _p = Promise.all([p1,p2,p4]);
  console.log(_p);//rejected -> '4444'
  
  
  //7 Promise.race(value);value一般为一个Promise对象 组成的数组,返回结果也是一个Promise对象.结果由第一个完成Promise状态改变的结果决定
  let p1 = new Promise((resolve,reject)=>{
      setTimeout(()=>{
          resolve('1111')
      },1000)
  })
  let p2 = Promise.resolve('2222')
  let p3 = Promise.reject('3333')
  let p = Promise.race([p1,p2]);
  let _p = Promise.race([p1,p3]);
  console.log(p); //fulfilled -> '2222'
  console.log(_p);//rejected -> '3333'
  

一个Promise 指定多个成功(then)/失败(catch)回调函数,是否都会调用?

  • 当Promise改变为对应状态时都会调用
//如果Promise函数状态没有改变那后面指定的回调(then)都不会执行
 let p1 = new Promise((resolve,reject)=>{
    // resolve('1111')
    reject('error')
  })
  p1.then(value=>{
    console.log(value);//1111
  })

  p1.then(value=>{
    console.log(value);//1111
  })
  p1.then(value=>{
    console.log(value);//1111
  },reason=>{
    console.log(reason);//error
  })

改变Promise状态和指定回调函数谁先谁后?

1.都有可能
1.1如果promise内部是同步函数就是先改变状态后执行回调,
1.2如果promise内部是异步函数就是先执行回调在改变状态.

中断Promise链?

  • 有且只有一种方式只有返回一个pending状态的Promise对象