Promise由浅入深

Promise是什么?

  1、Promise是ES6提供的进行异步编程的解决方案

  2、Promise是一个构造函数,用来封装一个异步操作,可以获取其成功或失败的值

  异步编程旧的操作都是回调函数的方式:(不利于阅读和异常处理)

    1)fs 文件操作

      require('fs').readFile('./index.js', (err, data) => { })

    2)ajax

      $.get('url', (data) => { })

     3)定时器

      setTimeout(() => { }, 1000);

读取文件时采用回调的方式和promise的区别:

  const util = require('util')
  const fs = require('fs')

  // 1、回调函数的写法
  fs.readFile('./resources/为学.md', (err, data) => {
    if (err) throw err
    console.log(data + '')
  })

  let readFile = util.promisify(fs.readFile) // 将回调函数风格的方法转为promise

  // 2、promise写法
  readFile('./resources/为学.md').then((data) => {
    console.log(data + '')
  })

  // 3、promise封装读取文件的方法
  function getFile(path) {
    return new Promise((resolve, reject) => {
      require('fs').readFile(path, (err, data) => {
        if (err) reject(err)
        resolve(data)
      })
    })
  }

  getFile('./resources/为学.md')
    .then((data) => {
      console.log(data + '')
    })
    .catch((err) => {
      console.log(err)
    })

promise的状态:

  它的状态是实例对象中的 PromiseState 属性的值,共有3个:

    pending      未决定的

    resolved/fulfilled  成功

    rejected      失败

  它的状态变化只有两种可能,一是由pending变为resolved,一是由pending变为rejected,并且一个promise对象的状态只能改变一次,不可能由成功变为失败或由失败变为成功

  如何改变promise对象的状态:

    1、调用reslove(),将promise的状态由pending变为resolved

    2、调用reject(),将promise的状态由pending变为rejected

    3、执行throw语句,可以写成throw new Error('出错啦')也可以写成throw ‘出错啦’,将promise的状态由pending变为rejected

  promise对象的值:

  它的值是实例对象中的 PromiseResult 属性,保存了promise对象成功/失败的结果,没有执行成功或者失败该属性值为undefined

    PromiseResult只能由resolve()和reject()改变,保存它们传来的值,在实例对象中用then()接收resolve()的值,用catch()接收reject()的值,或者是用then()方法中两个回调函数,第一个接收resolve()的值,第二个接收reject()的值

API:

  Promise(excutor){}

  执行器函数(excutor函数):(resolve,reject)=>{}

    resolve函数:内部定义成功时调用的函数 value=>{}

    reject函数:内部定义失败时调用的函数 err=>{}

  注意:执行器函数会在Promise内部立即同步调用,异步操作在执行器中执行

  then()方法

    (onResolved,onRejected)=>{}

    onResolved函数:成功的函数 (value)=>{}

    onRejected函数:失败的函数 (err)=>{}

  catch()方法

    (onRejected)=>{}

    onRejected函数:失败的函数 (err)=>{}

构造函数的方法:

  Promise.resolve()

    /*
      如果传入的参数为非promise类型的对象,则返回的结果为成功的promise对象
      如果传入的参数为promise类型的对象,则返回的结果决定了resolve的结果
    */
    let p = Promise.resolve(111)
    console.log(p)

    let p1 = Promise.resolve(new Promise((resolve, reject) => {
      reject('错误')
    }))
    p1.catch(err => {
      console.error(err)
    })

  Promise.reject()

    // 不管传入的是什么,都会返回失败的结果
    let p = Promise.reject(123)
    p.catch(err => { console.log(err) })
    console.log(p)
    // 即使传入的是一个成功的promise对象,返回的也依然是失败的结果,这个结果是成功的promise
    let p1 = Promise.reject(new Promise((resolve, reject) => {
      resolve(456)
    }))
    p1.catch(err => { console.log(err) })
    console.log(p1)

  Promise.all()

    /*
      如果数组中的promise对象都是成功的状态,那么返回的状态也是成功的,返回的结果是这三个参数组成的数组
      如果数组中的promise对象有一个是失败的状态,那么返回的状态就是失败的,返回的结果是第一个失败的promise的结果
    */
    let p = new Promise((resolve, reject) => {
      resolve('成功')
    })
    let p1 = Promise.resolve('ok')
    let p2 = Promise.resolve('OK!')

    const result = Promise.all([p, p1, p2])
    console.log(result) // PromiseState 的值为 fulfilled    PromiseResult 的值为 ['成功', 'ok', 'OK!']

  Promise.race()

    // race是赛跑的意思,返回的promise对象的状态和结果为数组中第一个执行完的promise的状态和结果
    let p = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('成功')
      })
    })
    let p1 = Promise.reject('err')
    let p2 = Promise.resolve('OK!')

    let result = Promise.race([p, p1, p2])
    console.log(result) // 返回p1的状态和结果

Promise的几个问题:

  1、只要promise的状态发生改变,即执行了resolve()或reject()或throw '',它指定的多个成功/失败回调函数都会调用

    let p = new Promise((resolve, reject) => {
      // resolve('成功')
      // reject('错误')
      throw '错误'
    })

    p.catch(err => {
      console.log(err)
    })
    p.catch(err => {
      console.log(err)
    })

  2、改变promise状态和指定回调函数谁先执行?正常情况下promise中都是异步任务,先执行then()方法再改变promise状态

    // 如果promise中是同步任务,那么再改变promise状态再指定回调函数(执行then()方法);如果promise中是异步任务,那么先指定回调函数(先执行then()方法)再改变promise状态,这种情况居多
    let p = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('成功')
      }, 100)
    })
    p.then(data => {
      console.log(data) // 此时是先指定回调函数再改变promise状态
    }, err => { console.log(err) })

  3、如何先改变promise状态再指定回调函数

    1)在执行器中直接调用 resolve()/reject()----同步任务

    2)延迟更长的时间才调用 then()

  4、什么时候能得到数据

    1)如果先指定回调,那么当状态发生改变时回调函数就会调用,得到数据----异步任务

    2)如果先改变状态,那么当指定回调时回调函数就会调用,得到数据----同步任务

x

原文地址:https://www.cnblogs.com/wuqilang/p/14105999.html