Promise 入门

前言:

在 Promise 中,异步操作的结果有三种状态:等待(pending)、已完成(fulfilled)和已拒绝(rejected)。当异步操作完成后,Promise 对象会从等待状态转变为已完成或已拒绝状态。如果异步操作成功完成,则 Promise 对象处于已完成状态,并携带着异步操作的返回值;如果异步操作发生错误,则 Promise 对象处于已拒绝状态,并携带着一个错误信息。

Promise 可以通过链式调用来实现多个异步操作依次执行的效果,这种方式比传统的回调函数更加简洁、灵活和易读。

目录

前言:

简介

 fs读取文件

Promise封装fs读取文件操作

封装ajax请求

promise的状态改变

Promise工作流程

promise API

关键问题

如何修改对象的状态

promise 如何串连多个操作任务?

promise 异常传透?

中断 promise 链?

自定义(手写)Promise


简介

1.抽象表达:

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

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

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

2. 具体表达

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

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

异步编程

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

3.特点:

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

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

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

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

1. 什么是回调地狱?

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

2.回调地狱的缺点?

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

3.解决方案?

promise 链式调用。

案例

Promise 形式实现 都是函数类型的数据

resolve 解决

reject 拒绝

//点击按钮,2 后显示是否中奖(30%概率中奖)
//若中奖弹出恭喜恭喜,奖品为 19万 RMB 劳斯莱斯优惠券。若未中奖弹出再接再厉

//生成随机数
function rand(m,n){
  return Math.ceil(Math.random() * (n-m+1)) + m-1;
  //Math.ceil()方法返回一个大于或等于数字的最小整数,即向上取整
 }
 
//获取元素对象
const btn = document.querySelector('#btn');

btn.addEventListener('click', function(){
  const p = new Promise((resolve, reject) => [
  setTimeout(() => [
    //30% 1-100 1 2 30
    //获取从1 - 1的一个随机数
    let n = rand(1, 100);
    //判断
    if(n <= 30){
      resolve(n); // 将 promise 对象的状态设置为 [成功J}elsef
     }else{
      reject(n); // 将 promise 对象的状态设置为 [失败]
     }
    }, 1000);
    });
  //调用 then 方法 value 值 reason 理由
  p.then((value) => {
      alert('恭喜恭喜,奖品为 1万 RMB 劳斯莱斯优惠券,中奖号码为'+value);
    }, (reason) => {alert("再接再厉,号码为'+reason);
   }),
 })
 

 fs读取文件

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

fs是node.js里面的一个模块,叫文件系统模块。

//Promise 形式
let p = new Promise((resolve,reject) => 
  fs .readFile('./resource/content.txt',(err, data) => {
    //如果出错
    if(err) reject(err);
    //如果成功
    resolve(data);
   });
  });
  
//调用 then
p.then(value=>{
  console.log(value.tostring());
 },reason =>(
    console.log(reason);
 })

Promise封装fs读取文件操作

封装一个函数 mineReadFile 读取文件内容

参数: path 文件路径

返回: promise 对象

function mineReadFile(path){
  return new Promise((resolve, reject) => {
    //读取文件
    require('fs').readFile(path, (err, data) =>{
    //判断
    if(err) reject(err);
    //成功
    resolve();
   });
  });
 }
   

mineReadFile('./resource/content.txt')
.then(value=>{
  //输出文件内容
  console.log(value.tostring());
  }reason=>[
    console.log(reason);
  });

promisify方法进行promise风格转化

传入一个遵循常见的错误优先的回调风格的函数

(即以 (err,value) =>... 回调作为最后一个参数),并返回一个返回 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());
});

封装ajax请求

封装一个函数 send AJAX 发送 GET AJAX 请求

参数URL

返回结果 Promise 对象

function sendAJAX(url){
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.responseType ='json';
    xhr.open("GET",ur1);
    xhr.send();
    //处理结果
    xhr.onreadystatechange = function(){
      if(xhr.readyState === 4){
      //判断成功
        if(xhr.status >= 20 && xhr.status < 300){
          //成功的结果
          resolve(xhr.response);
         }else{
           reject(xhr.status);
         }
        }
      }
  }); 
   

sendAJAX('https://api.apiopen.top/getJoke')
.then(value => {
  console.log(value);
 }, reason => {
  console.warn(reason);
 });

promise的状态改变

pending 变为 resolved

pending 变为 rejected

说明: 只有这 2 种,且一个 promise 对象只能改变一次。

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

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

Promise 的状态

实例对象中的一个属性

①PromiseState

pending 未决定的

resolved / fullfilled 成功

rejected 失败

②Promise 对象的值

实例对象中的另一个属性 PromiseResult

保存着对象[成功/失败]的结果

resolve

reject


Promise工作流程

promise API

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

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

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

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

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

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

(1) onResolved,函数: 成功的回调函数 (value) =>

(2) onRejected 函数: 失败的回调函数 (reason) =>说明: 指定用于得到成功 value 的成功回调和用于得到失败 reason 的失败回调返回一个新的 promise 对象

3. Promise.prototype.catch 方法:(onRejected) => { }

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

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

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

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

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

//如果传入的参数为 非Promise类型的对象,则返回的结果为成功promise对象

//如果传入的参数为 Promise 对象,则参数的结果决定了 resolve 的结果

5.Promise.reject 方法:(reason) =>{ }

(1)reason: 失败的原因

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

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

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

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

7.Promise.race 方法:(promises) =>{ }

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

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

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

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

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

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

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

(2)Promise.prototype.then 方法: (onResolved,onRejected) =>{onResolved 函数:成功的回调函数 (value) => { }

关键问题

如何修改对象的状态

let p = new Promise((resolve, reject) =>{
  //1.resolve 函数
  // resolve( 'ok'); // pending=> fulfilled (resolved)
  
  //2.reject 函数
  // reject("error");// pending=> rejected
  //3。抛出错误
  throw'出问题了';
});
console.log(p);

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

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

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

(1)都有可能,正常情况下是先指定回调再改变状态,但也可以先改状态再指定回调。(执行器函数是同步执行的,一般来说会先改变状态。如果resolve写在定时器里,则then先执行)

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

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

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

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

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

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

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

(2) 详细表达:

①如果抛出异常,新 promise 变为 reiected,reason 为抛出的异常

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

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

即默认result的状态为成功fulfilled的,即使是p.then调用了reject回调函数

如果p.then里面的回调函数有return,并且return了一个Promise对象

那么此时的resut的状态和由returh返的Pomise对象里的状态和值决定。


promise 如何串连多个操作任务?

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

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

.then的确返回promise对象,但这个对象的值由回调返回的值决定,这里没有声明返回值,所以返回undefined,那么下一个then获取到的值就是undefined,直接打印出来。

promise 异常传透?

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

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

返回pending的promise,状态没有改变,then方法不可以调用


中断 promise 链?

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

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


自定义(手写)Promise

function (window) {
  //Promise 构造函数
  //内部同步执行的函数excutor:(resolve,reject) => {
  function Promise(excutor) {
  }
 })
function Promise(executor){
   //resolve函数
    function resolve(data){
      
    }
    //reject函数
    function reject(data){
      
    }
    //同步调用[执行器函数]
    executor(resolve,reject);
}
Promise.prototype.then = function(onResolved, onRejected){ }

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值