1. promise基础

Promise 对象用于表示一个异步操作的最终完成 (或失败)及其结果值。

描述

一个 Promise 对象代表一个在这个 promise 被创建出来时不一定已知的值。它让您能够把异步操作最终的成功返回值或者失败原因和相应的处理程序关联起来。 这样使得异步方法可以像同步方法那样返回值:异步方法并不会立即返回最终的值,而是会返回一个 promise,以便在未来某个时候把值交给使用者。
一个 Promise 必然处于以下几种状态之一: :::warning

  • 待定(pending): 初始状态,既没有被兑现,也没有被拒绝。 ::: :::success

  • 已兑现(fulfilled): 意味着操作成功完成。 ::: :::danger

  • 已拒绝(rejected): 意味着操作失败。 :::

待定状态的 Promise 对象要么会通过一个值被兑现(fulfilled),要么会通过一个原因(错误)被拒绝(rejected)。当这些情况之一发生时,我们用 promise 的 then 方法排列起来的相关处理程序就会被调用。如果 promise 在一个相应的处理程序被绑定时就已经被兑现或被拒绝了,那么这个处理程序就会被调用,因此在完成异步操作和绑定处理方法之间不会存在竞争状态。

因为 Promise.prototype.thenPromise.prototype.catch 方法返回的是 promise, 所以它们可以被链式调用。
image.png

2. Promise异步的处理

定义Promise中的使用到的各个类型

  1. type ResolveType = (resolve: any) => any;
  2. type RejectType = (resolve: any) => any;
  3. type Executor = (reoslve: ResolveType, reject: RejectType) => any;
  4. export { ResolveType, RejectType, Executor };

1. 单异步 + 级联then

采用发布订阅模式可以实现单异步+级联then的功能

  1. import { ResolveType, RejectType, Executor } from "./actionType";
  2. export default class Promise<T = any> {
  3. public resolve!: ResolveType;
  4. public reject!: RejectType;
  5. public status: string;
  6. public resolve_executor_value: any;
  7. public reject_executor_value: any;
  8. // 保存成功状态要执行的函数
  9. public resolve_then_callbacks: (() => void)[] = [];
  10. // 保存失败状态要执行的函数
  11. public reject_then_callbacks: (() => void)[] = [];
  12. constructor(executor: Executor) {
  13. this.status = "pending"; //状态值
  14. // 成功
  15. this.resolve = (value: any) => {
  16. if (this.status === "pending") {
  17. console.log("进入到resolve方法");
  18. this.status = "success";
  19. this.resolve_executor_value = value;
  20. this.resolve_then_callbacks.forEach((callback) => callback());
  21. }
  22. };
  23. // 失败
  24. this.reject = (reason: any) => {
  25. if (this.status === "pending") {
  26. console.log("进入到reject方法");
  27. this.status = "reject";
  28. this.reject_executor_value = reason;
  29. this.reject_then_callbacks.forEach((callback) => callback());
  30. }
  31. };
  32. try {
  33. // 执行函数
  34. executor(this.resolve, this.reject);
  35. } catch (err) {
  36. this.status = "pending";
  37. // 失败则直接执行reject函数
  38. this.reject((err as any).toString());
  39. throw new Error("程序停止...");
  40. }
  41. }
  42. then(resolveInthen: ResolveType, rejectInThen: RejectType) {
  43. console.log("进入then方法");
  44. return new Promise((resolve, reject) => {
  45. let result;
  46. // 这里的this代表外部的Promise对象
  47. if (this.status === "success") {
  48. result = resolveInthen(this.resolve_executor_value); //ok
  49. resolve(result);
  50. }
  51. if (this.status === "reject") {
  52. result = rejectInThen(this.reject_executor_value);
  53. reject(result);
  54. }
  55. //生产者
  56. if (this.status === "pending") {
  57. console.log("进入到then方法的pending块");
  58. this.resolve_then_callbacks.push(() => {
  59. result = resolveInthen(this.resolve_executor_value);
  60. resolve(result);
  61. });
  62. this.reject_then_callbacks.push(() => {
  63. result = rejectInThen(this.reject_executor_value);
  64. reject(result);
  65. });
  66. }
  67. });
  68. }
  69. }
  70. export {};

测试函数

  1. import Promise from "./Promise";
  2. //
  3. let promise = new Promise((resolve, reject) => {
  4. // 模拟宏任务异步执行过程
  5. setTimeout(() => {
  6. resolve("成功了");
  7. }, 1000);
  8. });
  9. promise
  10. .then(
  11. (resolveData1) => {
  12. return console.log("第一个then成功了:", resolveData1), "ok";
  13. },
  14. (rejectData1) => {
  15. return console.log("第一个then失败了:", rejectData1), "fail1";
  16. }
  17. )
  18. .then(
  19. (resolveData1) => {
  20. return console.log("第二个then成功了:", resolveData1), "ok";
  21. },
  22. (rejectData1) => {
  23. return console.log("第二个then失败了:", rejectData1), "fail1";
  24. }
  25. );
  26. console.log("<----同步代码结束---->");
  27. export {};

2. 多异步+级联

如果then返回的是新的promise,涉及到多级异步,实现方法如下:

  1. import { ResolveType, RejectType, Executor } from "./actionType";
  2. export default class MyPromise<T = any> {
  3. public resolve!: ResolveType;
  4. public reject!: RejectType;
  5. public status: string;
  6. public resolve_executor_value: any;
  7. public reject_executor_value: any;
  8. // 保存成功状态要执行的函数
  9. public resolve_then_callbacks: (() => void)[] = [];
  10. // 保存失败状态要执行的函数
  11. public reject_then_callbacks: (() => void)[] = [];
  12. constructor(executor: Executor) {
  13. this.status = "pending"; //状态值
  14. // 成功
  15. this.resolve = (value: any) => {
  16. if (this.status === "pending") {
  17. this.status = "success";
  18. this.resolve_executor_value = value;
  19. this.resolve_then_callbacks.forEach((callback) => callback());
  20. }
  21. };
  22. // 失败
  23. this.reject = (reason: any) => {
  24. if (this.status === "pending") {
  25. this.status = "reject";
  26. this.reject_executor_value = reason;
  27. this.reject_then_callbacks.forEach((callback) => callback());
  28. }
  29. };
  30. try {
  31. // 执行函数
  32. executor(this.resolve, this.reject);
  33. } catch (err) {
  34. //console.log(err.toString())
  35. this.status = "pending";
  36. // 失败则直接执行reject函数
  37. this.reject(err);
  38. throw new Error("程序停止...");
  39. }
  40. }
  41. then(resolveInthen: ResolveType, rejectInThen: RejectType) {
  42. console.log("进入then方法");
  43. return new MyPromise((resolve, reject) => {
  44. let result: any;
  45. if (this.status === "success") {
  46. result = resolveInthen(this.resolve_executor_value); //ok
  47. resolve(result);
  48. }
  49. if (this.status === "reject") {
  50. result = rejectInThen(this.reject_executor_value);
  51. reject(result);
  52. }
  53. if (this.status === "pending") {
  54. console.log("进入到then方法的pending块");
  55. this.processManyAsyncAndSync(resolveInthen, rejectInThen, resolve, reject);
  56. }
  57. });
  58. }
  59. /**
  60. * 执行多个异步+多级then的处理方法
  61. * @param resolveInthen
  62. * @param rejectInThen
  63. * @param resolve
  64. * @param reject
  65. */
  66. processManyAsyncAndSync(
  67. resolveInthen: ResolveType,
  68. rejectInThen: RejectType,
  69. resolve: ResolveType,
  70. reject: RejectType
  71. ) {
  72. let result: any;
  73. this.resolve_then_callbacks.push(async () => {
  74. result = await resolveInthen(this.resolve_executor_value);
  75. if (isPromise(result)) {
  76. // 是异步的Promise对象
  77. result.then(
  78. (resolveSuccess) => {
  79. resolve(resolveSuccess);
  80. },
  81. (rejectSucess) => {
  82. reject(rejectSucess);
  83. }
  84. );
  85. } else {
  86. resolve(result); // 如果是普通的数据,不是异步的Promise对象
  87. }
  88. });
  89. this.reject_then_callbacks.push(() => {
  90. result = rejectInThen(this.reject_executor_value);
  91. reject(result);
  92. });
  93. }
  94. }
  95. function isPromise(val: any): val is Promise<any> {
  96. return isObject(val) && isFunction(val.then);
  97. }
  98. function isObject(val: any): val is Record<any, any> {
  99. return val !== null && typeof val === "object";
  100. }
  101. function isFunction(data: any): data is Function {
  102. return typeof data === "function";
  103. }
  104. export {};

这里的processManyAsyncAndSync利用async&await实现了异步,是一种不常见的处理方法。此外,还有另外一种比较常见的处理方法,使用then方法处理:

  1. processManyAsyncAndSync(
  2. resolveInthen: ResolveType,
  3. rejectInThen: RejectType,
  4. resolve: ResolveType,
  5. reject: RejectType
  6. ) {
  7. let result: any;
  8. this.resolve_then_callbacks.push(async () => {
  9. result = await resolveInthen(this.resolve_executor_value);
  10. if (isPromise(result)) {
  11. // 是异步的Promise对象
  12. result.then(
  13. (result) => {
  14. resolve(result);
  15. },
  16. (reason) => reject(reason)
  17. );
  18. } else {
  19. resolve(result); // 如果是普通的数据,不是异步的Promise对象
  20. }
  21. });
  22. this.reject_then_callbacks.push(() => {
  23. result = rejectInThen(this.reject_executor_value);
  24. reject(result);
  25. });
  26. }

测试如下:

  1. import Promise from "./Promise";
  2. //
  3. let promise = new Promise((resolve, reject) => {
  4. // 模拟宏任务异步执行过程
  5. setTimeout(() => {
  6. resolve("成功了");
  7. }, 1000);
  8. });
  9. promise
  10. .then(
  11. (resolveData1) => {
  12. console.log("第一个then成功了:", resolveData1);
  13. return new Promise((resolve, reject) => {
  14. setTimeout(() => {
  15. resolve("第二个异步操作");
  16. }, 1000);
  17. });
  18. },
  19. (rejectData1) => {
  20. return console.log("第一个then失败了:", rejectData1), "fail1";
  21. }
  22. )
  23. .then(
  24. (resolveData1) => {
  25. return console.log("第二个then成功了:", resolveData1), "ok";
  26. },
  27. (rejectData1) => {
  28. return console.log("第二个then失败了:", rejectData1), "fail1";
  29. }
  30. );
  31. console.log("<----同步代码结束---->");
  32. export {};

3. Promise.all()

  1. class Promise<T = any>{
  2. ...
  3. static all(promises: Promise[]): Promise {
  4. return new Promise((resolve, reject) => {
  5. let allPromiseResults: Array<any> = [];
  6. let executorIndex = 0;
  7. promises.forEach((promise, index) => {
  8. promise.then(
  9. (result) => {
  10. ProcessData(result, index);
  11. },
  12. (reason) => {
  13. reject(reason);
  14. return;
  15. }
  16. );
  17. });
  18. function ProcessData(result: any, index: number) {
  19. allPromiseResults[index] = result;
  20. executorIndex++;
  21. if (executorIndex === promises.length) {
  22. resolve(allPromiseResults);
  23. }
  24. }
  25. });
  26. }