Promise详解

一、Promise的理解和使用

1.Promise是什么?

1.1 理解

1.抽象表达:

​ 1)promise是一门新的技术(ES6规范)

​ 2)promise是JS中进行异步编程的新解决方案

​ 备注:旧方案是单纯使用回调函数

    例如:
    fs文件操作:require('fs').readFile('./index.html',(err,data)=>{})
    数据库操作
    AJAX:$.get('/server',(data)=>{})
    定时器:setTimeout(()=>{},2000)

2.具体表达:

​ 1)从语法上来说:Promise是一个构造函数

​ 2)从功能上来说:Promise对象用来封装一个异步操作并可以获取其成功/失败的结果值

1.2 为什么要用Promise?

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

​ 1)旧的:必须在启动异步任务前指定

​ 2)promise:启动异步任务 => 返回promise对象 => 给promise对象绑定回调函数(甚至可以在异步任务结束后指定多个回调函数)

2.支持链式调用,可以解决回调地狱问题(重要知识点

​ 1)什么是回调地狱?

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

	asyncFunc1(opt,(...args1) => {
        asynFunc2(opt,(...args2) => {
             asynFunc3(opt,(...agrs3) => {
                  asynFunc4(opt,(...args4) => {
                      // some operation
                  })
             })
        })
    })

​ 2)回调地狱的缺点?

​ 不利于阅读

​ 不便于异常处理

​ 3)解决方案?

​ promise链式调用

2.Promise初体验

  // promise实现
  // resolve 解决 函数类型的数据 异步成功时调用
  // reject  拒绝 函数类型的数据 异步失败时调用
  // promise 可以包裹一个异步操作
  btn.addEventListener('click',function(){
    const p = new Promise((resolve,reject) => {
      setTimeout(() => {
        let n = rand(1, 100);
        console.log(n);
        if (n <= 30) {
          resolve(n);  // 将 promise 对象的状态设置为 [成功]
        } else {
          reject(n);  // 将 promise 对象的状态设置为 [失败]
        }
      }, 1000);
    })
    // 回调写在then里
    // 调用 then 方法
    // resolve 和 reject 传递参数给 then 
    p.then((value) =>{
      // 第一个回调是异步成功的回调,即resolve的回调
      alert("恭喜中奖,奖品为10RMB 劳斯莱斯优惠卷,您的中奖号码是:" + value);
    },(reason) =>{
      // 第一个回调是异步失败的回调,即reject的回调
      alert("未中奖,再接再厉,您的号码是" + reason);
    })
  })

3.Promise封装操作

3.1 Promise封装fs模块

	/* 
  封装一个函数 mineReadFile 读取文件内容
  参数:patn 文件路径
  返回:promise 对象
 */
function mineReadFile(path) {
  return new Promise((resolve,reject) => {
    require('fs').readFile(path,(err,data) => {
      // 失败
      if(err) reject(err)
      // 成功
      resolve(data)
    })
  })
}
mineReadFile('./resource/content.txt').then(value => {
  // 输出文件内容
  console.log(value.toString());
},reason => {
  console.log(reason);
})

3.2 util.promisify方法

util.promisify:将回调函数风格的方法 转为 promise风格的方法

// 1.引入 util模块
const util = require("util");
// 2.引入 fs 模块
const fs = require("fs");
// 3.返回一个新的函数
const mineReadFile = util.promisify(fs.readFile);

mineReadFile("./resource/content.txt").then((value) => {
  console.log(value.toString());
});

4.Promise 的状态

​ 定义:promise实例对象中的一个属性(PromiseState),表示promise异步任务是否成功

​ 状态值:pending 未决定的 resolved / fulfilled 成功 rejected 失败

​ 状态值的改变:(1)pending 变为 resolve (2)pending 变为 reject

​ 说明:(1)只有这两种,且一个promise对象只能改变一次

​ (2)无论变为成功还是失败,都会有一个结果数据

​ (3)成功的结果数据一般称为 value,失败的结果数据一般称为 reason

5.Promise 对象的值

​ 定义:promise实例对象中的一个属性(PromiseResult),保存着异步任务成功/失败后的结果数据

​ 注:resolvereject 两个函数(即then里的函数)可以分别对 PromiseResult 的值进行修改

6.Promise 的 API

6.1 Promise 构造函数:Promise(executor){}

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

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

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

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

6.2 Promise.prototype.then 方法:(onResolved,onRejected) => {}

​ (1)onResolved 函数:成功的回调函数 (value) => {}

​ (2)onReject 函数:失败的回调函数(reason) => {}

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

6.3 Promise.prototype.cath 方法:(onrejected) => {}

​ (1)onrejected 函数:失败的回调函数 (reason) => {}

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

p.catch((reason) => {
      console.log(reason);
    });

6.4 Promise.resolve 方法:(value) => {}

​ (1)value:成功的数据或 promise 对象

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

    // 2.promise.resolve() :返回一个成功/失败的promise 对象,对象的值为括号里的参数的值
    // 2.1 如果传入的参数为 非promise类型的对象,则返回的结果为成功的peomise对象
    let p1 = Promise.resolve(521);
    console.log(p1);

    // 2.2 如果传入的参数为 promise对象,则参数的结果决定了 resolve 的结果
	let p2 = Promise.resolve(new Promise((resolve,reject) => {
      reject('Error')
    }))
    p2.catch(reason => {
      console.log(reason);
    })

6.5 promise.reject 方法:(reason) => {}

​ (1)reason:失败的原因

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

	// 括号里的参数就是失败结果
    let p3 = Promise.reject(666);
	// reject(成功的promise对象)后也返回失败的promise,失败的值为那个括号里的成功的promise对象

6.6 Promise.all 方法:(promises) => {}

​ (1)promises:包含 n 个 promise 的数组

​ (2)说明:返回一个新的 promise,只有所有的 promise 都成功才成功,只要有一个失败了就直接失败

​ (3)成功的值为:所有 promise 成功值组组成的数组;失败值为:第一个失败的promise 的结果

6.7 Promise.race 方法 (promise) => {}

​ (1)promise:包含n个promise的数组

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

7.Promise几个关键问题

7.1 状态改变

​ (1)resolve 函数:pending ==> resolved(fulfilled)

​ (2)reject 函数 :pending ==> rejected

​ (3)throw 抛出错误

7.2 一个promise指定多个成功/失败回调函数(then),都会调用吗

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

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

​ (1)都有可能,正常情况下是先指定回调再改变状态,但也可以先改变状态再指定回调

​ (2)如何先改状态再指定回调?

​ 1.在执行器中直接调用 resolve()/ reject()

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

​ (3)如何先指定回调再改变状态

resolve()reject() 写在异步任务(定时器)内

​ (3)什么时候才能得到数据?

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

​ 2.如果先改变状态,当指定回调时,回调函数就会调用,得到数据

​ 总结:只有状态改变时,回调函数才会执行,得到数据

7.4 promise.then()返回的新promise对象的结果状态由什么决定?

​ (1)简单表达:由 then()指定的回调函数执行的结果决定

​ (2)详细表达:

​ 1.如果抛出异常,新 promise 变为 rejected,reason为抛出的异常

​ 2.如果返回的是非promise的任意值,新promise变为resolved,value为返回的值

​ 3.如果返回的是另一个新promise,此 promise 的结果就会成为新promise的结果

7.5 promise 如何串联多个操作任务?

​ (1)promise 的 then() 返回一个新的 promise,可以看成 then() 的链式调用

​ (2)通过 then() 的链式调用串联多个同步/异步任务

7.6 promise 异常穿透

​ (1)当使用 promise 的 then() 链式调用时,可以在最后指定失败的回调

​ (2)前面任何操作出了异常,都会传到最后失败的回调中处理

7.7 中断 promise 链

​ (1)当使用 promsie 的 then 链式调用时,在中间中断,不再调用后面地回调函数

​ (2)办法:在回调函数中返回一个 pending 状态的 promise 对象

8.async 与 await

8.1 async 函数

​ (1)函数的返回值为promsie对象

​ (2)promsie对象的结果由async函数执行的返回值决定

8.2 await 表达式

​ (1)await右侧的表达式一般为 promsie 对象,但也可以是其他的值

​ (2)如果表达式是 成功的promsie 对象,await 返回的是 promise 成功的值

​ (3)如果表达式是 失败的promsie 对象,直接抛出错误,用 try…catch 解决

​ (4)如果表达式是其它值,直接将此值作为 await 的返回值

​ 注:(1)await 必须写在async 函数中,但 async 函数中可以没有 await

​ (2)如果 await 的 promsie 失败了,就会抛出异常,需要通过 try…catch 捕获处理

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值