《尚硅谷Web前端Promise教程从入门到精通》系列博客_ Promise介绍与基本使用


前言

为学习axios打基础。本尚硅谷Web前端Promise教程从入门到精通系列博客内容介绍。
Promise是ES6引入的进行异步编程的新的解决方案,从语法上说它是一个构造函数,可以封装异步的任务,并且可以对结果进行处理。Promise最大的好处在于可以解决回调地狱的问题,并且在指定回调和处理错误方面更加灵活,在Web或者App项目中应用十分广泛,无论前端还是后端都可以看到Promise的身影,且是现在面试的高频题目,想进入一线大厂必须掌握Promise内部运行的原理。
尚硅谷Web前端Promise教程从入门到精通系列博客主要包含以下五部分:Promise 介绍与基本使用Promise APIPromise 关键问题Promise 自定义封装async 与await


Promise 介绍与基本使用

1.Promise是什么?

1.1 理解

1.1.1 抽象表达:
  1. Promise 是一门新的技术(ES6规范)
  2. Promise 是JS 中进行异步编程的新解决方案
    备注:旧方案是单纯使用回调函数
    note:异步编程包括但不限于:文件操作、数据库操作、AJAX、定时器
1.1.2 具体表达:
  1. 从语法上来说: Promise是一个构造函数
  2. 从功能上来说: promise 对象用来封装一个异步操作并可以获取其成功/失败的结果值

1.2. 为什么要用Promise?

1.2.1. 指定回调函数的方式更加灵活
  1. 旧的: 必须在启动异步任务前指定
  2. promise: 启动异步任务 => 返回promie对象 => 给promise对象绑定回调函数(甚至可以在异步任务结束后指定/多个)
    note:回调函数是一种特殊的函数,它作为参数传递给另一个函数,并在被调用函数执行完毕后被调用。
1.2.2. 支持链式调用, 可以解决回调地狱问题
  1. 什么是回调地狱? 回调函数嵌套调用, 外部回调函数异步执行的结果是嵌套的回调执行的条件
    在这里插入图片描述
  2. 回调地狱的缺点? 不便于阅读、不便于异常处理
  3. 解决方案? promise 链式调用
  4. 终极解决方案? async/await

2.Promise初体验

看一下Promise在异步任务当中是如何使用的。需求:点一下“点击抽奖",在两秒后,页面弹窗展示是否中奖,中奖概率30%。
html文件代码如下:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>基本使用</title>
    <link crossorigin='anonymous' href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <div class="container">
        <h2 class="page-header">Promise 初体验</h2>
        <button class="btn btn-primary" id="btn">点击抽奖</button>
    </div>
    <script>
        //生成随机数
        function rand(m,n){
            return Math.ceil(Math.random() * (n-m+1)) + m-1;
        }
        /**
            点击按钮,  1s 后显示是否中奖(30%概率中奖)
                若中奖弹出    恭喜恭喜, 奖品为 10万 RMB 劳斯莱斯优惠券
                若未中奖弹出  再接再厉
        */
        //获取元素对象
        const btn = document.querySelector('#btn');
        //绑定单击事件
        btn.addEventListener('click', function(){
            //定时器
            // setTimeout(() => {
            //     //30%  1-100  1 2 30
            //     //获取从1 - 100的一个随机数
            //     let n = rand(1, 100);
            //     //判断
            //     if(n <= 30){
            //         alert('恭喜恭喜, 奖品为 10万 RMB 劳斯莱斯优惠券');
            //     }else{
            //         alert('再接再厉');
            //     }
            // }, 1000);
            //Promise 形式实现 Promise是个构造函数,所以可以进行对象的实例化,其在实例化时需要接收一个参数,
            //这个参数是个函数类型的值。
            // resolve 解决  函数类型的数据 当异步任务成功时调用
            // reject  拒绝  函数类型的数据 当异步任务失败时调用
            const p = new Promise((resolve, reject) => {
                setTimeout(() => {//由于Promise可以包裹异步操作,所以把setTimeout()函数包裹进来
                    //30%  1-100  1 2 30
                    //获取从1 - 100的一个随机数
                    let n = rand(1, 100);
                    //判断
                    if(n <= 30){
                        resolve(n); // 将 promise 对象的状态设置为 『成功』成功时调用resolve()
                    }else{
                        reject(n); // 将 promise 对象的状态设置为 『失败』 失败时调用reject()
                    }
                }, 1000);
            });

            console.log(p);
            //调用 then 方法 来进行值得输出,它要接收两个函数作为参数。第一个是成功时的回调函数,第二个是失败时的回调函数
            // value 值
            // reason 理由
            p.then((value) => {
                alert('恭喜恭喜, 奖品为 10万 RMB 劳斯莱斯优惠券, 您的中奖数字为 ' + value);
            }, (reason) => {
                alert('再接再厉, 您的号码为 ' + reason);
            });
        });
    </script>
</body>
</html>

3.Promise实践练习-fs读取文件

需求:从txt文件中读取一些汉字。
js文件代码如下:

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

//Promise 形式
let p = new Promise((resolve , reject) => {
    fs.readFile('./resource/content.txt', (err, data) => {//Promise包裹fs这个异步操作。./resource/content.txt随便存些汉字
        //如果出错
        if(err) reject(err);
        //如果成功
        resolve(data);
    });
});

//调用 then 
p.then(value=>{//形参只有一个,箭头函数这里简写,直接加"=>"
    console.log(value.toString());
}, reason=>{
    console.log(reason);
});

下图为运行结果:
在这里插入图片描述

4.Promise实践练习-AJAX请求段子接口

html文件代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Promise 封装 AJAX</title>
    <link crossorigin='anonymous' href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <div class="container">
        <h2 class="page-header">Promise 封装 AJAX 操作</h2>
        <button class="btn btn-primary" id="btn">点击发送 AJAX</button>
    </div>
    <script>
        //接口地址 https://api.apiopen.top/getJoke
        //获取元素对象
        const btn = document.querySelector('#btn');

        btn.addEventListener('click', function(){
            //创建 Promise
            const p = new Promise((resolve, reject) => {
                //1.创建对象
                const xhr = new XMLHttpRequest();
                //2. 初始化
                xhr.open('GET', 'https://api.apiopen.top/getJoke');
                //3. 发送
                xhr.send();
                //4. 处理响应结果
                xhr.onreadystatechange = function(){
                    if(xhr.readyState === 4){
                        //判断响应状态码 2xx   
                        if(xhr.status >= 200 && xhr.status < 300){
                            //控制台输出响应体
                            resolve(xhr.response);
                        }else{
                            //控制台输出响应状态码
                            reject(xhr.status);
                        }
                    }
                }
            });
            //调用then方法
            p.then(value=>{
                console.log("success " + value);
            }, reason=>{
                console.warn("fail " + reason);
            });
        });
    </script>
</body>
</html>

5.Promise封装fs读取文件操作

需求:
封装一个函数 mineReadFile 读取文件内容
参数: path 文件路径
返回: promise 对象
js文件代码如下:

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

mineReadFile('./resource/content.txt')//因为返回的是Promise对象,所以直接加".then"。
.then(value=>{
    //输出文件内容
    console.log(value.toString());
}, reason=>{
    console.log(reason);
});

下图为效果:
在这里插入图片描述

6.util.promisify方法进行promise风格转化

util.promisify官方描述
js文件代码如下:

//引入 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());
});

下图是效果:
在这里插入图片描述

7.Promise封装AJAX请求

html文件代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Promise封装AJAX操作</title>
</head>
<body>
    <script>
        /**
         * 封装一个函数 sendAJAX 发送 GET AJAX 请求
         * 参数   URL
         * 返回结果 Promise 对象
         */
        function sendAJAX(url){
            return new Promise((resolve, reject) => {
                const xhr = new XMLHttpRequest();
                xhr.responseType = 'json';
                xhr.open("GET", url);
                xhr.send();
                //处理结果
                xhr.onreadystatechange = function(){
                    if(xhr.readyState === 4){
                        //判断成功
                        if(xhr.status >= 200 && xhr.status < 300){
                            //成功的结果
                            resolve(xhr.response);
                        }else{
                            reject(xhr.status);
                        }
                    }
                }
            });
        }
    
        sendAJAX('https://api.apiopen.top/getJok')
        .then(value => {
            console.log(value);
        }, reason => {
            console.warn(reason);
        });
    </script>
</body>
</html>

8.Promise对象状态属性介绍

Promise 的状态实例对象中的一个内置属性:[Promisestate」取值有以下三种情况:
pending 未决定的
resolved/fullfilled 成功
rejected 失败
我们在控制台输出一个promise对象可得到如下结果:
在这里插入图片描述

9.Promise对象结果属性介绍

实例Promise对象中的另一个属性 [PromiseResult」
保存着异步任务「成功/失败」的结果
仅能通过resolve或者reject赋值

10.Promise工作流程

在这里插入图片描述
Promise对象拥有两个实例方法then()和catch()。
then()方法
成功和失败的回调函数我们是通过then()添加,在promise状态改变时分别调用,也就是说没有执行改变状态的代码,then()方法不会被调用。promise构造函数中通常都是异步的,所以then方法往往都先于resolve和reject方法执行。所以promise内部需要有一个存储fulfill时调用函数的数组和一个存储reject时调用函数的数组。
then方法可以接收两个参数,且通常都是函数。第一个参数会添加到fulfill时调用的数组中,第二个参数添加到reject时调用的数组中。
当promise状态fulfill时,会把resolve(value)中的value值传给调用的函数中。
同理,当promise状态reject时,会把reject(reason)中的reason值传给调用的函数。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值