十三、Promise

郁子大约 4 分钟约 1130 字笔记ECMAScript尚硅谷李强

(一)基本语法

  • PromiseES6 引入的异步编程的新解决方案
    • 是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果
  • Promise 构造函数: Promise (excutor) {}
  • Promise.prototype.then 方法
  • Promise.prototype.catch 方法
// 实例化Promise对象
const p = new Promise(function (resolve, reject) {
  setTimeout(function () {
    // 获得一个数据
    let data = "数据库中的用户数据";

    // // 调用resolve后p对象状态变为“成功”
    // resolve(data);

    // 调用reject后p对象状态变为“失败”
    reject(data);
  }, 1000);
});

// 调用Promise对象的then方法
p.then(
  function (value) {
    // p为成功时执行
    console.log(value);
  },
  function (reason) {
    // p为失败时指向
    console.error(reason);
  },
);

(二)读取文件

    为学

天下事有难易乎?
为止,则难者亦易矣;
不为,则易者亦难矣。
// 1.引入nodejs中的fs模块
const fs = require("fs");

// 2.调用方法读取文件
// fs.readFile("./resources/为学.md", (err, data) => {
//   // 如果失败则抛出错误
//   if (err) throw err;
//   // 如果成功则输出内容
//   console.log(data.toString());
//   /**
//    * cd '.\ECMAScript6-11\'
//    * node .\21.Promise读取文件.js
//    */
// });

// 3.使用Promise封装
const p = new Promise(function (resolve, reject) {
  fs.readFile("./resources/为学.md", (err, data) => {
    // 如果失败
    if (err) reject(err);
    // 如果成功
    resolve(data);
  });
});
p.then(
  function (value) {
    console.log(value.toString());
  },
  function (reason) {
    console.log("读取失败!");
  },
);

(三)发送 Ajax 请求

1.传统 xhr

// 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) {
    // 判断响应状态码:200-299即成功
    if (xhr.status >= 200 && xhr.status < 300) {
      // 表示成功
      console.log(xhr.response);
    } else {
      // 如果失败
      console.error(xhr.status);
    }
  }
};

2.使用 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) {
      // 判断响应状态码:200-299即成功
      if (xhr.status >= 200 && xhr.status < 300) {
        // 表示成功
        resolve(xhr.response);
      } else {
        // 如果失败
        reject(xhr.status);
      }
    }
  };
});
// 指定回调
p.then(
  function (value) {
    console.log(value);
  },
  function (reason) {
    console.error(reason);
  },
);

(四)Promise.prototype.then

1.调用 then 方法

// 创建Promise对象
const p = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("用户数据");
    // reject('出错啦');
  }, 1000);
});

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

2.then 方法返回的结果

  • then 方法的返回结果是 Promise 对象
  • 对象状态由回调函数的执行结果来决定
  • 回调函数中返回的结果是 非 Promise 类型 的数据 => resolve (状态成功,返回值为对象的成功的值)
const result = p.then(
  (value) => {
    console.log(value);
    // 0.没有返回值
    // [[PromiseState]]: "fulfilled"
    // [[PromiseResult]]: undefined

    // 1.非Promise类型
    // return 123;
    // // [[PromiseState]]: "fulfilled"
    // // [[PromiseResult]]: 123

    // 2.是Promise对象
    // return new Promise((resolve, reject) => {
    //   // Promise内部任务多数是异步的,但是也可以是同步任务
    //   // resolve('ok');
    //   // // [[PromiseState]]: "fulfilled"
    //   // // [[PromiseResult]]: "ok"

    //   reject("error");
    //   // [[PromiseState]]: "rejected"
    //   // [[PromiseResult]]: "error"
    // });

    // 3.抛出错误
    throw new Error("出错啦!");
    // [[PromiseState]]: "rejected"
    // [[PromiseResult]]: Error: 出错啦!
  },
  (reason) => {
    console.warn(reason);
  },
);
console.log(result);

3.then 方法可以链式调用

  • 指定回调可以只指定一个成功或者一个失败
p.then((reason) => {
  console.log(reason);
}).then((value) => {
  console.log(value);
});

(五)读取多个文件

    插秧诗
    布袋和尚

手把青秧插满田,
低头便见水中天。
心地清净方为道,
退步原来是向前。

    观书有感
    作者:朱熹

半亩方塘一鉴开,
天光云影共徘徊。
问渠那得清如许?
为有源头活水来。

1.回调地狱读取文件

// 引入fs模块
const fs = require("fs");

// 回调地狱读取文件
fs.readFile("./resources/为学.md", (err1, data1) => {
  fs.readFile("./resources/插秧诗.md", (err2, data2) => {
    fs.readFile("./resources/观书有感.md", (err3, data3) => {
      let result = `${data1}\r\n${data2}\r\n${data3};`;
      console.log(result);
    });
  });
});

2.使用 Promise 实现

// 引入fs模块
const fs = require("fs");

const p = new Promise((resolve, reject) => {
  fs.readFile("./resources/为学.md", (err, data) => {
    resolve(data);
    // data是buffer类型,使用toString转为可读字符串
  });
});
p.then((value) => {
  // console.log(value.toString());
  return new Promise((resolve, reject) => {
    fs.readFile("./resources/插秧诗.md", (err, data) => {
      resolve([value, data]);
    });
  });
})
  .then((value) => {
    // console.log(value); // 为学+插秧诗
    return new Promise((resolve, reject) => {
      fs.readFile("./resources/观书有感.md", (err, data) => {
        // 压入
        value.push(data);
        resolve(value);
      });
    });
  })
  .then((value) => {
    console.log(value.join("\r\n"));
  });

(六)Promise.prototype.catch

// 创建Promise对象
const p = new Promise((resolve, reject) => {
  setTimeout(() => {
    // 设置p对象的状态为失败,并设置失败的值
    reject("出错啦");
  }, 1000);
});

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

// 指定Promise失败的回调
p.catch((reason) => {
  console.warn(reason);
});
上次编辑于: