• (八) ES6 新特性 —— promise


    CSDN话题挑战赛第2期
    参赛话题:学习笔记

    目录

    promise的实例化

    Promise封装读取文件

    promise封装读取AJAX

    Promise-then方法

    需求:按顺序读取三个文件的内容

    catch方法


    Promise 是 ES6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数, 用来封装异步操作并可以获取其成功或失败的结果。

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

    2) Promise.prototype.then 方法

    3) Promise.prototype.catch 方法

    promise的实例化

    promise实例化接受一个参数,而且这个参数是一个函数,有两个形参:resolve, reject

    里面还有一个异步操作:

    1. const p = new Promise(function (resolve, reject) {
    2. setTimeout(function () {
    3. }, 1000);
    4. });
    '
    运行

    promise对象有三个状态:初始化、成功、失败

    当我们在异步函数里面调用一个resolve之后,对象的状态就会变成成功

    1. const p = new Promise(function (resolve, reject) {
    2. setTimeout(function () {
    3. let data = '数据库中的用户数据';
    4. resolve(data);
    5. }, 1000);
    6. });
    '
    运行

    而当我们调用reject之后,对象的状态就会变成失败。

    1. const p = new Promise(function (resolve, reject) {
    2. setTimeout(function () {
    3. let err = '数据读取失败';
    4. reject(err);
    5. }, 1000);
    6. });

    此时:我们可以调用promise 对象的 then 方法

    then方法接收两个函数类型的参数。

    成功的函数是value,失败的是reason

    如果promise调用的是resolve——成功,那么then就会就会执行第一个回调函数

    如果promise调用的是reject——失败,那么then就会就会执行第二个回调函数

    1. p.then(
    2. function (value) {
    3. console.log(value);
    4. },
    5. function (reason) {
    6. console.error(reason);
    7. }
    8. );

    调用resolve返回结果:

    调用reason返回结果:

    Promise封装读取文件

    我们想要读取为学.md文件里面的内容并对他做一个输出。

    如果不用promise的话,我们可以这样做:

    1. fs.readFile('./resources/为学.md', (err, data) => {
    2. //如果失败, 则抛出错误
    3. if (err) throw err;
    4. //如果没有出错, 则输出内容
    5. console.log(data.toString());
    6. });

    正常输出,没有问题。

    当我们使用promise封装时:

    1. const p = new Promise(function (resolve, reject) {
    2. // 读取文件也是一个异步操作
    3. fs.readFile("./resources/为学.md", (err, data)=>{
    4. //判断如果失败
    5. if(err) reject(err);
    6. //如果成功
    7. resolve(data);
    8. });
    9. });
    10. p.then(function(value){
    11. console.log(value.toString());
    12. }, function(reason){
    13. console.log("读取失败!!");
    14. });
    '
    运行

    也可以正常读出文件内容。

    promise封装读取AJAX

    1. // 接口地址: https://api.apiopen.top/getJoke
    2. const p = new Promise((resolve, reject) => {
    3. //1. 创建对象
    4. const xhr = new XMLHttpRequest();
    5. //2. 初始化
    6. xhr.open('GET', 'https://api.apiopen.top/getJoke');
    7. // 跨域的话可以去设置一下响应头
    8. //response.setHeader('Access-Control-Allow-Origin', '*');
    9. //3. 发送
    10. xhr.send();
    11. //4. 绑定事件, 处理响应结果
    12. xhr.onreadystatechange = function () {
    13. //判断
    14. if (xhr.readyState === 4) {
    15. //判断响应状态码 200-299
    16. if (xhr.status >= 200 && xhr.status < 300) {
    17. //表示成功
    18. resolve(xhr.response);
    19. } else {
    20. //如果失败
    21. reject(xhr.status);
    22. }
    23. }
    24. };
    25. });
    26. //指定回调
    27. p.then(
    28. function (value) {
    29. console.log(value);
    30. },
    31. function (reason) {
    32. console.error(reason);
    33. }
    34. );
    '
    运行

    Promise-then方法

    1. const p = new Promise((resolve, reject) => {
    2. setTimeout(() => {
    3. reject('出错啦');
    4. }, 1000);
    5. });
    6. const result = p.then(
    7. (value) => {
    8. console.log(value);
    9. },
    10. (reason) => {
    11. console.warn(reason);
    12. }
    13. );
    14. console.log(result);
    '
    运行

    当我们接收then方法的返回结果时我们发现他是一个Promise对象,对象状态由回调函数的返回结果决定,如果回调函数中返回的结果是一个非Promise类型的属性,状态为成功,返回值为对象的成功的值。

    1. const p = new Promise((resolve, reject) => {
    2. setTimeout(() => {
    3. resolve('成功啦');
    4. }, 1000);
    5. });
    6. const result = p.then(
    7. (value) => {
    8. console.log(value);
    9. return 123;
    10. },
    11. (reason) => {
    12. console.warn(reason);
    13. }
    14. );
    15. console.log(result);
    '
    运行

    如果返回的值是一个成功的promise对象:

    1. const result = p.then(
    2. (value) => {
    3. console.log(value);
    4. return new Promise((resolve, reject) => {
    5. resolve('ok');
    6. });
    7. },
    8. (reason) => {
    9. console.warn(reason);
    10. }
    11. );
    12. console.log(result);

    回调函数返回的是一个Promise,那么这个Promise的状态就会影响Then方法返回的一个Promise的状态,而且这个Promise成功返回的值就是then方法返回的值。

    再看返回的失败的Promise对象:

    1. const result = p.then(
    2. (value) => {
    3. console.log(value);
    4. return new Promise((resolve, reject) => {
    5. // resolve('ok');
    6. reject('error');
    7. });
    8. //3. 抛出错误
    9. // throw new Error('出错啦!');
    10. throw '出错啦!';
    11. },
    12. (reason) => {
    13. console.warn(reason);
    14. }
    15. );
    16. console.log(result);

    如果回调函数返回的是一个失败,那么then方法返回的也是一个失败,失败值就是then方法的失败值。

    说白了就是里面的异步操作决定外面的异步操作

    再来看看抛出错误的选项:

    1. const result = p.then(
    2. (value) => {
    3. console.log(value);
    4. //3. 抛出错误
    5. throw new Error('出错啦!');
    6. // throw '出错啦!';
    7. },
    8. (reason) => {
    9. console.warn(reason);
    10. }
    11. );
    12. console.log(result);

    状态也是一个失败的Promise的状态,错误值就是Error抛出来的那个值。

    根据then方法的以上特性:我们来看一下then方法的链式调用

    p.then((value) => {}).then((value) => {});

    需求:按顺序读取三个文件的内容

    方法一:层级嵌套

    1. const fs = require("fs");
    2. fs.readFile('./resources/为学.md', (err, data1)=>{
    3. fs.readFile('./resources/插秧诗.md', (err, data2)=>{
    4. fs.readFile('./resources/观书有感.md', (err, data3)=>{
    5. let result = data1 + '\r\n' +data2 +'\r\n'+ data3;
    6. console.log(result);
    7. });
    8. });
    9. });
    '
    运行

    方法二:Promise

    1. const p = new Promise((resolve, reject) => {
    2. fs.readFile("./resources/为学.md", (err, data) => {
    3. resolve(data);
    4. });
    5. });
    6. p.then(value => {
    7. // value是第一个文件内容,data是第二个文件内容
    8. return new Promise((resolve, reject) => {
    9. fs.readFile("./resources/插秧诗.md", (err, data) => {
    10. resolve([value, data]); // 1. 这里返回成功,那么then方法也会返回成功,
    11. // 而且then方法返回成功的值就是这块返回成功的值 即两个文件的数组
    12. });
    13. });
    14. }).then(value => {
    15. // 2. 所以这里的value就是第一个文件结合了第二个文件后的值
    16. return new Promise((resolve, reject) => {
    17. fs.readFile("./resources/观书有感.md", (err, data) => {
    18. //压入
    19. value.push(data); //value就是三个文件的值
    20. resolve(value);// 3. 再把value传给下一个then
    21. });
    22. })
    23. }).then(value => {
    24. console.log(value.join('\r\n'));
    25. });

    catch方法

    catch不同于then方法,他只需指定一个方法就可以了。

    1. const p = new Promise((resolve, reject) => {
    2. setTimeout(() => {
    3. //设置 p 对象的状态为失败, 并设置失败的值
    4. reject('出错啦!');
    5. }, 1000);
    6. });
    7. p.catch(function (reason) {
    8. console.warn(reason);
    9. });
    '
    运行

  • 相关阅读:
    二叉(搜索)树的最近公共祖先 ●●
    Docker学习笔记
    文本生成中的采样策略
    代码随想录算法训练营第二十三天|669 修剪二叉搜索树 108 将有序数组转换为二叉搜索树 538 把二叉搜索树转换为累加树
    antd+react Hook弹窗改进版
    聚苯乙烯PS彩色胶乳微球:红色/蓝色/黑色/绿色胶乳微球介绍和制备方法
    java多线程-多线程技能
    Shell脚本完成pxe装机配置
    电子电器架构 —— 网关通道设计原则
    Day 36 贪心算法 part05 : 435. 无重叠区间 763.划分字母区间 56. 合并区间
  • 原文地址:https://blog.csdn.net/a45667/article/details/127116634