【Promise】Promise的理解与使用 阶段一

一、Promise介绍

1、概念:

​ Promise是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。

通俗讲,Promise是一个许诺、承诺,是对未来事情的承诺,承诺不一定能完成,但是无论是否能完成都会有一个结果。

  • Pending 正在做。。。
  • Resolved 完成这个承诺
  • Rejected 这个承诺没有完成,失败了

​ Promise 用来预定一个不一定能完成的任务,要么成功,要么失败

​ 在具体的程序中具体的体现,通常用来封装一个异步任务,提供承诺结果

Promise 是异步编程的一种解决方案,主要用来解决回调地狱的问题,可以有效的减少回调嵌套。真正解决需要配合async/await

2、特点:

​ (1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称Fulfilled)和Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。

​ (2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从Pending变为Resolved和从Pending变为Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。

3、缺点:

​ (1)无法取消Promise,一旦新建它就会立即执行,无法中途取消。和一般的对象不一样,无需调用。

​ (2)如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。

​ (3)当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)


二、Promise是什么?

Ⅰ-理解
  1. 抽象表达:

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

​ 2)Promise 是 JS 中进行异步编程的新解决方案 备注:旧方案是单纯使用回调函数

  1. 具体表达:
  1. 从语法上来说: Promise 是一个构造函数

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

Ⅱ-promise 的状态
a) promise 的状态

实例对象中的一个属性 『PromiseState』

  • pending 未决定的
  • resolved / fullfilled 成功
  • rejected 失败
b) promise 的状态改变
  1. pending 变为 resolved

  2. pending 变为 rejected

说明: 只有这 2 种, 且一个 promise 对象只能改变一次 无论变为成功还是失败, 都会有一个结果数据 成功的结果数据一般称为 value, 失败的结果数据一般称为 reason

Ⅲ-promise的基本流程

Promise系统学习_promise工作流程

Ⅳ-promise的基本使用
1.使用 promise 封装基于定时器的异步
<script >
  function doDelay(time) {
    // 1. 创建 promise 对象(pending 状态), 指定执行器函数
    return new Promise((resolve, reject) => {
      // 2. 在执行器函数中启动异步任务
      console.log('启动异步任务')
      setTimeout(() => {
        console.log('延迟任务开始执行...')
        const time = Date.now() // 假设: 时间为奇数代表成功, 为偶数代表失败
        if (time % 2 === 1) { // 成功了
          // 3. 1. 如果成功了, 调用 resolve()并传入成功的 value
          resolve('成功的数据 ' + time)
        } else { // 失败了
          // 3.2. 如果失败了, 调用 reject()并传入失败的 reason
          reject('失败的数据 ' + time)
        }
      }, time)
    })
  }
const promise = doDelay(2000)
promise.then(// promise 指定成功或失败的回调函数来获取成功的 vlaue 或失败的 reason
    value => {// 成功的回调函数 onResolved, 得到成功的 vlaue
      console.log('成功的 value: ', value)
    },
    reason => { // 失败的回调函数 onRejected, 得到失败的 reason
      console.log('失败的 reason: ', reason)
    },
  ) <
  /script>
2.使用 promise 封装 ajax 异步请求
<script >
  /*
  可复用的发 ajax 请求的函数: xhr + promise
  */
  function promiseAjax(url) {
    return new Promise((resolve, reject) => {
      const xhr = new XMLHttpRequest()
      xhr.onreadystatechange = () => {
        if (xhr.readyState !== 4) return
        const {
          status,
          response
        } = xhr
        // 请求成功, 调用 resolve(value)
        if (status >= 200 && status < 300) {
          resolve(JSON.parse(response))
        } else { // 请求失败, 调用 reject(reason)
          reject(new Error('请求失败: status: ' + status))
        }
      }
      xhr.open("GET", url)
      xhr.send()
    })
  }
promiseAjax('https://api.apiopen.top2/getJoke?page=1&count=2&type=vid
    eo ')
    .then(
      data => {
        console.log('显示成功数据', data)
      },
      error => {
        alert(error.message)
      }
    ) </script>
3.fs模块使用Promise
const fs = require('fs');

//回调函数 形式----------------------------------------------------
 fs.readFile('./resource/content.txt', (err, data) => {
     // 如果出错 则抛出错误
     if(err)  throw err;
     //输出文件内容
     console.log(data.toString());
 });

//Promise 形式-----------------------------------------------------------
/**
 * 封装一个函数 mineReadFile 读取文件内容
 * 参数:  path  文件路径
 * 返回:  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);
});
4.异常穿透

可以在每个then()的第二个回调函数中进行err处理,也可以利用异常穿透特性,到最后用catch去承接统一处理,两者一起用时,前者会生效(因为err已经将其处理,就不会再往下穿透)而走不到后面的catch

在每个.then()中我可以将数据再次传出给下一个then()

mineReadFile('./11.txt').then(result=>{
  console.log(result.toString())
  return result
},err=>console.log(err))
.then(data=>console.log(data,"2222222"))
.catch(err=>console.log("这是catch的"))
5.util.promisify方法

可以将函数直接变成promise的封装方式,不用再去手动封装

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

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

2、为什么要用Promise?

Ⅰ-指定回调函数的方式更加灵活

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

Ⅱ-支持链式调用, 可以解决回调地狱问题

1、什么是回调地狱

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

Promise系统学习_回调地狱

2、回调地狱的缺点?

不便于阅读 不便于异常处理

3、解决方案?

promise 链式调用,

用来解决回调地狱问题,但是只是简单的改变格式,并没有彻底解决上面的问题真正要解决上述问题,一定要利用promise再加上await和async关键字实现异步传同步

4、终极解决方案?

promise +async/await

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值