Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xgqfrms/242e610a02f24ff9afbc417dae2924f9 to your computer and use it in GitHub Desktop.
Save xgqfrms/242e610a02f24ff9afbc417dae2924f9 to your computer and use it in GitHub Desktop.
Promises/A+ 规范, js 实现 Promise

Promises/A+ 规范, js 实现 Promise

// @ts-ignore

export {};

// function Promise(callback) {
function Promise(this: any, callback) {
  let self = this;
  self.status = 'pending';
  self.value = undefined;
  self.onResolvedCallbacks = [];
  self.onRejectedCallbacks = [];
  function resolve(value) {
    if (value instanceof Promise) {
      // @ts-ignore
      return value.then(resolve, reject);
    }
    setTimeout(function () {
      if (self.status == 'pending') {
        self.value = value;
        self.status = 'resolved';
        self.onResolvedCallbacks.forEach(item => item(self.value));
      }
    });
  }
  function reject(value) {
    setTimeout(function () {
      if (self.status == 'pending') {
        self.value = value;
        self.status = 'rejected';
        self.onRejectedCallbacks.forEach(item => item(value));
      }
    });
  }
  try {
    callback(resolve, reject);
  } catch (e) {
    reject(e);
  }
}
//
function resolvePromise(promise2, promise, resolve, reject) {
  if (promise2 === promise) {
    return reject(new TypeError('循环引用'));
  }
  let then, called;
  if (promise != null && ((typeof promise == 'object' || typeof promise === "function"))) {
    try {
      then = promise.then;
      if (typeof then === 'function') {
        then.call(promise, function (value) {
          if (called)return;
          called = true;
          resolvePromise(promise2, value, resolve, reject);
        }, function (reason) {
          if (called)return;
          called = true;
          reject(reason);
        });
      } else {
        resolve(promise);
      }
    } catch (e) {
      if (called)return;
      called = true;
      reject(e);
    }
  } else {
    resolve(promise);
  }
}

Promise.prototype.then = function (onFulfilled, onRejected) {
  let self = this;
  onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function (value) {
    return value
  };
  onRejected = typeof onRejected === 'function' ? onRejected : function (value) {
    throw value
  };
  let promise2;
  if (self.status == 'resolved') {
    promise2 = new Promise(function (resolve, reject) {
      setTimeout(function () {
        try {
          let promise = onFulfilled(self.value);
          resolvePromise(promise2, promise, resolve, reject);
        } catch (e) {
          reject(e);
        }
      });
    });
  }
  if (self.status == 'rejected') {
    promise2 = new Promise(function (resolve, reject) {
      setTimeout(function () {
        try {
          let promise = onRejected(self.value);
          resolvePromise(promise2, promise, resolve, reject);
        } catch (e) {
          reject(e);
        }
      });
    });
  }
  if (self.status == 'pending') {
    promise2 = new Promise(function (resolve, reject) {
      self.onResolvedCallbacks.push(function (value) {
        try {
          let promise = onFulfilled(value);
          resolvePromise(promise2, promise, resolve, reject);
        } catch (e) {
          reject(e);
        }
      });
      self.onRejectedCallbacks.push(function (value) {
        try {
          let promise = onRejected(value);
          resolvePromise(promise2, promise, resolve, reject);
        } catch (e) {
          reject(e);
        }
      });
    });
  }
  return promise2;
}

Promise.prototype.catch = function (onRejected) {
  return this.then(null, onRejected);
}

Promise.resolve = function (value) {
  return new Promise(function (resolve, reject) {
    if (typeof value !== null && typeof value === 'object' && typeof value.then === 'function') {
      value.then();
    } else {
      resolve(value);
    }
  })
};

Promise.reject = function (reason) {
  return new Promise(function (resolve, reject) {
    reject(reason);
  })
}

Promise.all = function (promises) {
  return new Promise(function (resolve, reject) {
    let result: any = [];
    // let result = [];
    let count = 0;
    for (let i = 0; i < promises.length; i++) {
      promises[i].then(function (data) {
        result[i] = data;
        count += 1;
        if (count == promises.length) {
          resolve(result);
        }
      }, function (err) {
        reject(err);
      });
    }
  });
}

Promise.race = function (promises) {
  return new Promise(function (resolve, reject) {
    for (let i = 0; i < promises.length; i++) {
      promises[i].then(function (data) {
        resolve(data);
      },function (err) {
        reject(err);
      });
    }
  });
}

Promise.deferred = Promise.defer = function () {
  var defer = {};
  // let defer = {
  //   promise: null,
  //   resolve: null,
  //   reject: null,
  // };
  // @ts-ignore
  defer.promise = new Promise(function (resolve, reject) {
    // @ts-ignore
    defer.resolve = resolve;
    // @ts-ignore
    defer.reject = reject;
  })
  return defer;
}

// module.exports = Promise;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment