Promise学习笔记

1.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(()=>{},1000);
    

2.为什么要使用Promise

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

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

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

回调地狱

1.什么是回到地狱?

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

示例:

const fs = require('fs');
fs.readfile('./resouce/1.html', (err, data1) => {
    if (err) {
        throw err;
    }
    fs.readfile('./resouce/2.html', (err, data2) => {
        if (err) {
            throw err;
            fs.readfile('./resouce/3.html', (err, data3) => {
                if (err) {
                    throw err;
                    console.log(data1 + data2 + data3);
                }
            });
        }
    });
});
2.回调地狱的缺点
  1. 不便于阅读
  2. 不便于异常处理
3.解决方案

promise链式调用

3.Promise初体验

1.体验1:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>promise初体验</title>
</head>

<body>
    <div style="width: 80%;height: 30;text-align: center;">
        <h1>promise初体验</h1>
        <button id="btn">点击抽检</button>
    </div>
    <script>
        function read(m, n) {
            return Math.ceil(Math.random() * (m - m + 1)) + m - 1;
        }
        // //获取元素对象
        // const btn = document.querySelector('#btn');
        // //绑定事件
        btn.addEventListener('click', () => {
            // setTimeout(() => {
            //     //获取1到100的随机数
            //     let n = read(1, 100);
            //     if (n <= 30) {
            //         alert('恭喜你中奖了!');
            //     } else {
            //         alert('再接再厉!');
            //     }
            // }, 1000);


            //Promise 形式实现
            const p = new Promise((resolve, reject) => {
                setTimeout(() => {
                    let n = read(1, 100);
                    if (n <= 30) {
                        resolve();

                    } else {
                        reject();

                    }
                }, 1000);
            });

            p.then(() => {
                alert('恭喜你中奖了!');
            }, () => {
                alert('再接再厉!');
            });
        });



    </script>
</body>

</html>

2.体验2(promise回调中获取成功失败值)

//Promise 形式实现
const p = new Promise((resolve, reject) => {
    setTimeout(() => {
        let n = read(1, 100);
        if (n <= 30) {
            resolve(n);
        } else {
            reject(n);
        }
    }, 1000);
});

p.then((value) => {
    alert('恭喜你中奖了!' + value);
}, (reason) => {
    alert('再接再厉!' + reason);
});

3.体验3

//Promise形式
const p = new Promise((resolve, reject) => {
    //出错
    if (err) {
        reject();
    }
    reject();
});

p.then(value => {
    console.log(value.toString());
}, reason => {
    console.log(reason.toString());
});

4.体验4

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div>
        <h2>Promise 封装 AJAX 操作</h2>
        <button id="btn">点击发送Ajax</button>
    </div>
    <script>
        const btn = document.querySelector('#btn');
        btn.addEventListener('click', () => {
            // // 1.创建对象
            // const xhr = new XMLHttpRequest();
            // //2.初始化
            // xhr.open('GET', 'https://api.apipen.top/getJoke');
            // // 3.发送
            // xhr.send();
            // // 4.处理响应结果
            // xhr.onreadystatechange = () => {
            //     if (xhr.readyState === 4) {
            //         //判断响应状态码为2xxx
            //         if (xhr.status >= 200 && xhr.status < 300) {
            //             // 打印响应体
            //             console.log(xhr.response);
            //         } else {
            //             // 输出响应状态码
            //             console.log(xhr.status);
            //         }
            //     }
            // }

            // 使用promise
            const p = new Promise((resolve, reject) => {
                // 1.创建对象
                const xhr = new XMLHttpRequest();
                //2.初始化
                xhr.open('GET', 'https://api.apipen.top/getJoke');
                // 3.发送
                xhr.send();
                // 4.处理响应结果
                xhr.onreadystatechange = () => {
                    if (xhr.readyState === 4) {
                        //判断响应状态码为2xxx
                        if (xhr.status >= 200 && xhr.status < 300) {
                            // 打印响应体
                            resolve(xhr.response);
                        } else {
                            // 输出响应状态码
                            reject(xhr.status);
                        }
                    }
                }
            });

            p.then(value => {
                console.log(value);
            }, reason => {
                console.warn(reason);
            });
        });
    </script>
</body>

</html>

5.封装练习

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.warn(reason);
});

6.node.js中util.promisify方法

/**
  * node.js中util.promisify 方法
  * 解释:接收回调风格函数 返回promise
*/
//引入util模块
const util = require('util');
//引入fs模块
const fs = require('fs');
//返回新函数 promise
let mineReadFile = util.promisify(fs.readFile);

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

7.使用Promise封装ajax操作

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>使用promise封装Ajax请求</title>
</head>

<body>
    <script>
        // 1.封装一个函数sendAjax 发送 GET请求  参数:URL 返回结果:promise对象
        function sedAJAX(url) {
            return new Promise((resolve, reject) => {
                const xhr = new XMLHttpRequest();
                xhr.responseType = 'json';
                xhr.open('GET', url);
                //处理结果
                xhr.onreadystatechange = function () {
                    //判断是否成功
                    if (xhr.readyState === 4) {
                        if (xhr.status >= 200 && xhr.status < 300) {
                            //成功
                            resolve(xhr.response);
                        } else {
                            reject(xhr.status);
                        }
                    }
                }
            });
        }

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

</body>

</html>

4.Promise对象

1.Promise状态

状态值改变
  1. pending变为resolved
  2. pending变为rejected

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

Promise的3种状态

实例对象的一个属性 【PromiseState】

  • pending 未决定的

  • resolved / fulfilled 成功

  • rejected 失败

2.Promise对象值

实例对象的另一个属性 【PromiseResult】

保存异步任务成功或失败的结果

3.Promise基本流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CYYH7Eyj-1649561429782)(E:\笔记\image\image-20220403180323084.png)]

5.Promise使用

1.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)=>{}
// 如果传入参数为非promise类型的对象,则返回成功的promise对象
// 如果传入的参数为promise对象,则返回结果为promise对象的结果
let p1 = Promise.resolve(521);
let p2 = Promise.reject(new Promise((resolve, reject) => {
    resolve('ok');
}));

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

5.Promise.reject方法:(reason)=>{}
//不管返回类型是不是promise类型对象,结果都返回失败,如果是promise类型对象,则返回失败,失败结果为成功或失败的promise对象
let p3 = Promise.reject(new Promise((resolve, reject) => {
resolve('ok');
}));

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

6.Promise.all方法:(promises)=>{}
  1. promises:包含n个promise的数组

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

7.Promise.race 方法:(promises)=>{}
  1. promises:包含n个promise的数组

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

8.改变promise对象状态的三种方法
  1. 调用resolve(), pending => fulfilled(resolved)
  2. 调用reject(),pending => rejected
  3. 抛出异常 throw ‘失败’;
9.Promise对象值改变和指定回调问题
  1. 当Promise对象中执行的是同步任务时,则先改变promise状态值,再指定回调,并执行回调函数
  2. 当Promise对象中执行的是异步任务时,先指定回调,再改变状态值,等状态值改变再执行回调函数

6.async函数

async function main() {
    // async方法返回一个Promise对象
    // 1.返回非promise类型参数时 方法结果为成功,成功结果为返回值
    // return 520;
    // 2.返回promise类型参数时,方法结果为改Promise对象结果
    // return new Promise((resolve, reject) => {
    //     reject('失败!');
    // });
    //3.抛出异常,则结果为失败,失败结果为异常结果
    throw '失败!';
};

console.log(main());

7.await表达式

  1. await右侧表达式一般为promise对象,但也可以是其他值
  2. 如果表达式是promise对象,await返回的是promise成功的值
  3. 如果表达式是其他值,直接将此值作为await的返回值

注意事项

  1. await必须写在async函数中,但async函数中可以没有await
  2. 如果await的promise失败了,就会抛出异常,需要通过try…catch捕获异常处理
async function main() {
    let p1 = new Promise((resolve, reject) => {
        resolve("成功了");
    });
    let p4 = new Promise((resolve, reject) => {
        reject("失败了");
    })
    //1.右侧为Promise的情况,awai会返回promise对象成功的结果
    //2.非Promise情况,则返回右侧原本结果
    //失败的情况,需要使用try...catch捕获才能拿到失败结果
    let p2 = await p1;
    let p3 = await 10;
    try {
        let p5 = await p4;
    } catch (e) {
        console.log(e);
    }
    console.log(p2);
    console.log(p3);

8.async和await对象结合实践

案例一:文件读取
// 需求:读取多个文件,拼接输出
// 回调方式:
const fs = require('fs');
fs.readfile('./resouce/1.html', (err, data1) => {
    if (err) {
        throw err;
    }
    fs.readfile('./resouce/2.html', (err, data2) => {
        if (err) {
            throw err;
            fs.readfile('./resouce/3.html', (err, data3) => {
                if (err) {
                    throw err;
                    console.log(data1 + data2 + data3);
                }
            });
        }
    });
});

const util = require('util');
const mineReadFile = util.promisify(fs.readfile);
// async与await
async function main() {
    //1.获取文件1内容
    try {
        let data1 = await mineReadFile('./resource/1.html');
        let data2 = await mineReadFile('./resource/2.html');
        let data3 = await mineReadFile('./resource/3.html');
        console.log(data1 + data2 + data3);
    } catch (error) {
        console.warn(error);
    }


}

main();
案例二:ajax操作
// 1.封装一个函数sendAjax 发送 GET请求  参数:URL 返回结果:promise对象
function sedAJAX(url) {
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.responseType = 'json';
        xhr.open('GET', url);
        //处理结果
        xhr.onreadystatechange = function () {
            //判断是否成功
            if (xhr.readyState === 4) {
                if (xhr.status >= 200 && xhr.status < 300) {
                    //成功
                    resolve(xhr.response);
                } else {
                    reject(xhr.status);
                }
            }
        }
    });
}

async function main() {
    try {
        let data = await sedAJAX('https://ap.apiopen.top/getJoke');
        console.log(data);
    } catch (error) {
        console.log(error);
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值