Promise/A+ 规范

英文:https://promisesaplus.com/
翻译:https://malcolmyu.github.io/2015/06/12/Promises-A-Plus/

参考:

手写Promise - 图1

class

  1. class Promise1 {
  2. constructor(executor) {
  3. // 初始化state为等待态
  4. this.state = "pending";
  5. // 成功的值
  6. this.value = undefined;
  7. // 失败的原因
  8. this.reason = undefined;
  9. // 成功存放的数组
  10. this.onResolvedCallbacks = [];
  11. // 失败存放法数组
  12. this.onRejectedCallbacks = [];
  13. let resolve = (value) => {
  14. // state改变,resolve调用就会失败
  15. if (this.state === "pending") {
  16. // resolve调用后,state转化为成功态
  17. this.state = "fulfilled";
  18. // 储存成功的值
  19. this.value = value;
  20. // 一旦resolve执行,调用成功数组的函数
  21. this.onResolvedCallbacks.forEach((fn) => fn());
  22. }
  23. };
  24. let reject = (reason) => {
  25. // state改变,reject调用就会失败
  26. if (this.state === "pending") {
  27. // reject调用后,state转化为失败态
  28. this.state = "rejected";
  29. // 储存失败的原因
  30. this.reason = reason;
  31. // 一旦reject执行,调用失败数组的函数
  32. this.onRejectedCallbacks.forEach((fn) => fn());
  33. }
  34. };
  35. // 如果executor执行报错,直接执行reject
  36. try {
  37. executor(resolve, reject);
  38. } catch (err) {
  39. reject(err);
  40. }
  41. }
  42. }

then

  1. then(onFulfilled, onRejected) {
  2. switch (this.state) {
  3. case "pending":
  4. this.onResolvedCallbacks.push(() => {
  5. onFulfilled(this.value); // onFulfilled传入到成功数组
  6. });
  7. this.onRejectedCallbacks.push(() => {
  8. onRejected(this.reason); // onRejected传入到失败数组
  9. });
  10. break;
  11. case "fulfilled": // 状态为fulfilled,执行onFulfilled,传入成功的值
  12. onFulfilled(this.value);
  13. break;
  14. case "rejected":
  15. onRejected(this.reason); // 状态为rejected,执行onRejected,传入失败的原因
  16. break;
  17. }
  18. }

支持链式调用

  1. function then(onFulfilled, onReject) {
  2. return new Promise1((resolve, reject) => {
  3. // 封装前一个promise成功时执行的函数
  4. let fulfilled = () => {
  5. try {
  6. const result = onFulfilled(this.value); // 承前
  7. return result instanceof Promise1
  8. ? result.then(resolve, reject)
  9. : resolve(result); //启后
  10. } catch (err) {
  11. reject(err);
  12. }
  13. };
  14. let rejected = () => {
  15. try {
  16. const result = onReject(this.reason);
  17. return result instanceof Promise1
  18. ? result.then(resolve, reject)
  19. : reject(result);
  20. } catch (err) {
  21. reject(err);
  22. }
  23. };
  24. switch (this.state) {
  25. case "pending":
  26. this.onResolvedCallbacks.push(fulfilled);
  27. this.onRejectedCallbacks.push(rejected);
  28. break;
  29. case "fulfilled":
  30. fulfilled();
  31. break;
  32. case "rejected":
  33. rejected();
  34. break;
  35. }
  36. });
  37. }

Promise.resolve

Promsie.resolve(value)可以将任何值转成值为 value 状态是 fulfilled 的 Promise,但如果传入的值本身是 Promise 则会原样返回它。

  1. Promise.resolve = function(value) {
  2. // 如果是 Promsie 或 thenable对象,则直接输出它
  3. if (value instanceof Promise || ((typeof value === 'object') && 'then' in value)) {
  4. return value;
  5. }
  6. return new Promise(resolve => resolve(value))
  7. }

Promise.reject

  1. Promise.reject = function (reason) {
  2. return new Promise(function (resolve, reject) {
  3. reject(reason);
  4. });
  5. }

Promise.all

  1. function PromiseAll(promises) {
  2. return new Promise((resolve, reject) => {
  3. // 参数判断
  4. if (!Array.isArray(promises)) {
  5. throw new TypeError("promises must be an array");
  6. }
  7. let result = []; // 存放结果
  8. let count = 0; // 记录有几个resolved
  9. promises.forEach((promise, index) => {
  10. promise.then(
  11. (res) => {
  12. result[index] = res;
  13. count++;
  14. count === promises.length && resolve(result); // 判断是否已经完成
  15. },
  16. (err) => {
  17. reject(err);
  18. }
  19. );
  20. });
  21. });

Promise.race

  1. PromiseRace = (promises) => {
  2. return new Promise((resolve, reject) => {
  3. promises.forEach((p) => {
  4. // 哪个先改变状态,我们返回的Promise也将会是什么状态
  5. Promise.resolve(p).then(resolve).catch(reject);
  6. });
  7. });
  8. };

Promise.allSettled

  1. function PromiseAllSettled(promises) {
  2. let arr = [],
  3. count = 0;
  4. return new Promise((resolve, reject) => {
  5. promises.forEach((item, i) => {
  6. Promise.resolve(item).then(
  7. (res) => {
  8. arr[i] = { status: "fulfilled", val: res };
  9. count += 1;
  10. if (count === promises.length) resolve(arr);
  11. },
  12. (err) => {
  13. arr[i] = { status: "rejected", val: err };
  14. count += 1;
  15. if (count === promises.length) resolve(arr);
  16. }
  17. );
  18. });
  19. });
  20. }