promise基础

promise

用途

  • Promise 对象用于异步计算
  • 一个Promise 表示一个现在、将来或永不可能可用的值
  • 可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
  • 可以在对象之间传递和操作Promise,帮助我们处理队列

异步产生的原因

  • JavaScript为检查表单而生
  • 创造它的首要目标是操作DOM
  • 所以,JavaScript的操作大多是异步的

image-20200902191652003

异步操作的常见语法

事件侦听与相应

image-20200902191749750

回调

image-20200902191815028

异步回调的问题

1568774611975

promise的理解和使用

是什么

理解
  • 抽象表达
    • Promise 是 JS 中进行异步编程的新的解决方案(旧的是谁?)
  • 具体表达
    • 从语法上来说: Promise 是一个构造函数
    • 从功能上来说: promise 对象用来封装一个异步操作并可以获取其结果
promise的状态改变
  • pending 变为 resolved
  • pending 变为 rejected
  • 说明: 只有这 2 种, 且一个 promise 对象只能改变一次
    • 无论变为成功还是失败, 都会有一个结果数据
    • 成功的结果数据一般称为 value, 失败的结果数据一般称为 reason
promise的基本流程

image-20200902194021468

promise的基本使用
	// 1. 创建一个新的promise对象
    const p = new Promise((resolve, reject) => { // 执行器函数

    // 2.执行异步任务
    setTimeout(() => {
        const time = Date.now();
    	// 3.1 成功,调用resolve(value)
        if(time %2 == 0){
            resolve('成功的数据,time=' + time);
        }
        // 3.2 失败,调用reject(reason)
        else{
            reject('失败的数据,time=' + time);
        }
    

    }, 1000)

    })
	
    // 4. 通过promise的then()指定成功和失败的回调函数
    p.then(
        value =>{ // 接收得到成功的value数据   onResolved
            console.log('成功的回调',value)
        },
        reason =>{ // 接收得到失败的reason数据  onRejected
            console.log('失败的回调',reason)
        }
    )

为什么要用promise

指定回调函数的方式更加灵活
  • 旧的: 必须在启动异步任务前指定(时间灵活)

    • 纯回调新式,必须在启动异步任务前,执行回调函数
    • promise,一般在启动任务之后,可以在启动之后
  • promise: 启动异步任务 => 返回promie对象 => 给promise对象绑定回调函
    数(甚至可以在异步任务结束后指定/多个)

支持链式调用, 可以解决回调地狱问题
  1. 什么是回调地狱?

     doSomething(function(result) {
            doSomethingElse(result, function(newResult) {
              doThirdThing(newResult, function(finalResult) {
                console.log('Got the final result: ' + finalResult)
              }, failureCallback)
            }, failureCallback)
          }, failureCallback)
    

    回调函数嵌套调用, 外部回调函数异步执行的结果是嵌套的回调执行的条件

  2. 回调地狱的缺点?
    不便于阅读
    不便于异常处理

  3. 解决方案?
    promise 链式调用

 doSomething()
      .then(function(result) {
        return doSomethingElse(result)
      })
      .then(function(newResult) {
        return doThirdThing(newResult)
      })
      .then(function(finalResult) {
        console.log('Got the final result: ' + finalResult)
      })
      .catch(failureCallback)
  1. 终极解决方案?
    async/await
 async function request() {
        try {
          const result = await doSomething()
          const newResult = await doSomethingElse(result)
          const finalResult = await doThirdThing(newResult)
          console.log('Got the final result: ' + finalResult)
        } catch (error) {
          failureCallback(error)
        }
      }

如何使用promise

API

Promise 构造函数: Promise (excutor) {}

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

(2) resolve 函数: 内部定义成功时我们调用的函数 value => {}

(3) reject 函数: 内部定义失败时我们调用的函数 reason => {}

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

Promise构造函数: Promise (excutor) {}
  • excutor函数: 同步执行 (resolve, reject) => {}
  • resolve函数: 内部定义成功时我们调用的函数 value => {}
  • reject函数: 内部定义失败时我们调用的函数 reason => {}
  • 说明: excutor会在Promise内部立即同步回调,异步操作在执行器中执行
Promise.prototype.then方法: (onResolved, onRejected) => {}
  • onResolved函数: 成功的回调函数 (value) => {}
  • onRejected函数: 失败的回调函数 (reason) => {}
  • 说明: 指定用于得到成功value的成功回调和用于得到失败reason的失败回调
  • 返回一个新的promise对象
Promise.prototype.catch方法: (onRejected) => {}
  • onRejected函数: 失败的回调函数 (reason) => {}
  • 说明: then()的语法糖, 相当于: then(undefined, onRejected)
  new Promise((resolve, reject) => {
    setTimeout(() => {
        // resolve('成功的数据')
        reject('失败的数据')
    }, 1000)
  }).then(
    value => {
        console.log('onResolved()1', value)
    }
  ).catch(
    reason => {
        console.log('onRejected()1', reason)
    }
  )
Promise.resolve方法: (value) => {}
  • value: 成功的数据或promise对象
  • 说明: 返回一个成功/失败的promise对象
// 产生一个成功值为1的promise对象
   const p1 = new Promise((resolve, reject) => {
       setTimeout(() => {
        resolve(1)
       }, 100);
   })
   const p2 = Promise.resolve(2);

//    p1.then(value => {console.log(value)})
//    p2.then(value => {console.log(value)})

Promise.reject方法: (reason) => {}
  • reason: 失败的原因
  • 说明: 返回一个失败的promise对象
const p3 = Promise.reject(3);
//p3.catch(reason => {console.log(reason)})
Promise.all方法: (promises) => {}
  • promises: 包含n个promise的数组
  • 说明: 返回一个新的promise, 只有所有的promise都成功才成功, 只要有一个失败了就直接失败
const pAll = Promise.all([p1, p2, p3]);
// 失败的原因是p3对应的reject(3),不要p3就可以成功
 pAll.then(
     values => {
        console.log('all onResolved()', values)// values的顺序要和promises数组中的顺序一致,跟执行完成的先后顺序无关
     },
     reason => {
        console.log('all onRejected()', reason)
     }
   )

Promise.race方法: (promises) => {}
  • promises: 包含n个promise的数组
  • 说明: 返回一个新的promise, 第一个完成的promise的结果状态就是最终的结果状态,状态由第一个完成的决定,如果第一个有延迟,则第二个先完成
const pRace = Promise.race([p1, p2, p3])
   pRace.then(
     value => {
        console.log('race onResolved()', value)
     },
     reason => {
        console.log('race onRejected()', reason)
     }
   )
promise 的几个关键问题
1.如何改变promise的状态?
  • (1)resolve(value): 如果当前是pendding就会变为resolved
  • (2)reject(reason): 如果当前是pendding就会变为rejected
  • (3)抛出异常: 如果当前是pendding就会变为rejected
const p = new Promise((resolve, reject) => {
      // resolve(1) // promise变为resolved成功状态
      // reject(2) // promise变为rejected失败状态
      // throw new Error('出错了') // 抛出异常, promse变为rejected失败状态, reason为 抛出的error
      throw 3 // 抛出异常, promse变为rejected失败状态, reason为 抛出的3
    })
    p.then(
      value => {},
      reason => {console.log('reason', reason)}
    )
    p.then(
      value => {},
      reason => {console.log('reason2', reason)}
    )
2.一个 promise 指定多个成功/失败回调函数, 都会调用吗?

当 promise 改变为对应状态时都会调用

p.then(
      value => {},
      reason => {console.log('reason', reason)}
    )
    p.then(
      value => {},
      reason => {console.log('reason2', reason)}
    )
3.改变promise状态和指定回调函数谁先谁后?
  • 都有可能, 正常情况下是先指定回调(then),再改变状态(同时指定数据), 但也可以先改状态再指定回调
// 常规: 先指定回调函数, 后改变的状态
    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)}
// 通过定时器,后面的定时器比前面的晚
 const p = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(1) // 后改变的状态(同时指定数据), 异步执行回调函数
      }, 1000);
    })

    setTimeout(() => {
      p.then(
        value => {console.log('value3', value)},
        reason => {console.log('reason3', reason)}
      )
    }, 1100);
  • 如何先改状态再指定回调?

​ ①在执行器中直接调用resolve()/reject()
​ ②延迟更长时间才调用then()

  • 什么时候才能得到数据?

​ ①如果先指定的回调, 那当状态发生改变时, 回调函数就会调用, 得到数据
​ ②如果先改变的状态, 那当指定回调时, 回调函数就会调用, 得到数据

4.promise.then()返回的新 promise 的结果状态由什么决定
  • 简单表达:
    • 由then()指定的回调函数执行的结果决定
  • 详细表达:
    • ①如果抛出异常, 新promise变为rejected, reason为抛出的异常
    • ②如果返回的是非promise的任意值, 新promise变为resolved, value为返回的值
    • ③如果返回的是另一个新promise, 此promise的结果就会成为新promise的结果
5.promise 如何串连多个操作任务?
  • promise的then()返回一个新的promise, 可以开成then()的链式调用
  • 通过then的链式调用串连多个同步/异步任务
6.promise 异常传透?
  • 当使用promise的then链式调用时, 可以在最后指定失败的回调,
  • 前面任何操作出了异常, 都会传到最后失败的回调中处理
7.中断promise链?
  • 当使用promise的then链式调用时, 在中间中断, 不再调用后面的回调函数
  • 办法: 在回调函数中返回一个pendding状态的promise对象

async

  • 用在函数中得到异步的Promise对象,默认是fulfilled

加了async相当于,语法糖

image-20200904120510616

可以通过throw,抛出错误,改变状态

image-20200904120332588

image-20200904120442069

  • 放到async函数里,配合await关键词,将异步改成同步

    等await后面出来结果之后,再给result

image-20200904120809842

image-20200904121104201

  • 25
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值