Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【学习笔记】Promise介绍 #2

Open
zjgyb opened this issue Apr 9, 2020 · 0 comments
Open

【学习笔记】Promise介绍 #2

zjgyb opened this issue Apr 9, 2020 · 0 comments

Comments

@zjgyb
Copy link
Owner

zjgyb commented Apr 9, 2020

Promise 的语法可以看阮一峰大大的Promise 对象

特点

Promise 对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。一旦状态改变,就不会再变,只有两种可能:从 pending 变为 fulfilled 和从 pending 变为 rejected。

缺点:

  1. 无法取消Promise,一旦新建它就会立即执行,无法中途取消
  2. 不设置回调函数,Promise内部抛出的错误,不会反映到外部
  3. 当处于pending状态时,无法得知目前进展状态

例子

红绿灯问题

红灯三秒亮一次,绿灯一秒亮一次,黄灯二秒亮一次

function red() {
  console.log("red");
}
function green() {
  console.log("green");
}
function yellow() {
  console.log("yellow");
}

const light = (timer, cb) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      cb();
      resolve();
    }, timer);
  });
};

const p1 = () => {
  return Promise.resolve()
    .then(() => light(3000, red))
    .then(() => light(1000, green))
    .then(() => light(2000, yellow))
    .then(() => p1());
};

p1();

写一个 Promise

基本 Promise

根据Promise/A+中的各项 promise 特点,然后写一个 promise

const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

function resolvePromise(promise2, x, resolve, reject) {
  // 2.3.1
  if (promise2 === x) {
    return reject(TypeError("不能循环调用"));
  }
  let called = false; // 判断是否已经调用了resolve和reject,因为它们只能调用一次
  // 2.3.2
  if (x instanceof Promise) {
    if (x.status === PENDING) {
      x.then(
        y => {
          resolvePromise(promise2, y, resolve, reject);
        },
        err => {
          reject(err);
        }
      );
    } else {
      x.then(resolve, reject);
    }
  } else if (x !== null && (typeof x === "object" || typeof x === "function")) {
    // 2.3.3
    // 判断then是否会抛出错误 如果then是一个Getter有可能会报错
    try {
      let then = x.then;
      if (typeof then === "function") {
        then.call(
          x,
          y => {
            if (called) return;
            called = true;
            resolvePromise(promise2, y, resolve, reject);
          },
          err => {
            if (called) return;
            called = true;
            reject(err);
          }
        );
      } else {
        if (called) return;
        called = true;
        resolve(x);
      }
    } catch (err) {
      // 2.3.3.3.4
      if (called) return;
      called = true;
      reject(err);
    }
  } else {
    // 2.3.4
    resolve(x);
  }
}

class Promise {
  constructor(executor) {
    // 初始状态为pending
    this.status = PENDING;
    // 初始值为null
    this.value = null;
    // 保存成功回调函数
    this.onFulfilledCallback = [];
    // 保存失败回调函数
    this.onRejectedCallback = [];
    // 成功回调
    const resolve = value => {
      if (value instanceof Promise) {
        return value.then(resolve, reject);
      }

      setTimeout(() => {
        // 把pending状态转换为fulfilled状态
        if (this.status === PENDING) {
          this.status = FULFILLED;
          this.value = value;
          this.onFulfilledCallback.forEach(cb => cb(this.value));
        }
      });
    };
    // 失败回调
    const reject = reason => {
      setTimeout(() => {
        // 把pending状态转换为rejected状态
        if (this.status === PENDING) {
          this.status = REJECTED;
          this.value = reason;
          this.onRejectedCallback.forEach(reason => reason(this.value));
        }
      });
    };

    try {
      executor(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }

  then(onFulfilled, onRejected) {
    // 如果不是函数,那么给一个函数使其能够传递参数给后面
    onFulfilled =
      typeof onFulfilled === "function" ? onFulfilled : value => value;
    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : reason => {
            throw reason;
          };
    let promise2;
    // 2.2.2
    if (this.status === FULFILLED) {
      return (promise2 = new Promise((resolve, reject) => {
        setTimeout(() => {
          // onFulfilled有可能执行失败
          try {
            // 判断x返回的是不是一个promise
            let x = onFulfilled(this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (err) {
            reject(err);
          }
        });
      }));
    }

    if (this.status === REJECTED) {
      return (promise2 = new Promise((resolve, reject) => {
        setTimeout(() => {
          try {
            let x = onRejected(this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (err) {
            reject(err);
          }
        });
      }));
    }

    if (this.status === PENDING) {
      return (promise2 = new Promise((resolve, reject) => {
        this.onFulfilledCallback.push(() => {
          try {
            // 判断x返回的是不是一个promise
            let x = onFulfilled(this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (err) {
            reject(err);
          }
        });

        this.onRejectedCallback.push(() => {
          try {
            let x = onRejected(this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (err) {
            reject(err);
          }
        });
      }));
    }
  }

  catch(onRejected) {
    this.then(null, onRejected);
  }
}

Promise.resolve & Promise.reject

Promise.resolve()等价于下面的写法

用法介绍

Promise.resolve("foo");
// 等价于
new Promise(resolve => resolve("foo"));

实现代码

class Promise {
  // ...
  static resolve(value) {
    return new Promise((resolve, reject) => {
      resolve(value);
    });
  }

  static reject(reason) {
    return new Promise((resolve, reject) => {
      reject(reason);
    });
  }
  // ...
}

Promise.all & Promise.race

// 记录是否所有的Promise已经返回值
function gen(times, cb) {
  const result = [];
  let count = 0;
  return function(i, data) {
    result[i] = data;
    if (++count === times) {
      cb(result);
    }
  };
}

class Promise {
  // ...
  static all(promises) {
    return new Promise((resolve, reject) => {
      const len = promises.length;
      const done = gen(len, resolve);
      for (let i = 0; i < len; i++) {
        promises[i].then(data => done(i, data), reject);
      }
    });
  }

  static race(promises) {
    return new Promise((resolve, reject) => {
      const len = promises.length;
      for (let i = 0; i < len; i++) {
        promises[i].then(resolve, reject);
      }
    });
  }
  // ...
}

参考文章

@zjgyb zjgyb changed the title Promise介绍 【学习笔记】Promise介绍 Apr 20, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant