{"id":13671511,"url":"https://github.com/wuxianqiang/promise","last_synced_at":"2025-04-15T15:38:13.413Z","repository":{"id":126583107,"uuid":"119988526","full_name":"wuxianqiang/promise","owner":"wuxianqiang","description":"实现promise","archived":false,"fork":false,"pushed_at":"2018-03-16T09:15:48.000Z","size":17,"stargazers_count":6,"open_issues_count":1,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-03-28T21:51:12.250Z","etag":null,"topics":["javascript","promise"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wuxianqiang.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-02-02T13:59:58.000Z","updated_at":"2020-05-21T16:48:14.000Z","dependencies_parsed_at":"2023-03-13T11:36:49.141Z","dependency_job_id":null,"html_url":"https://github.com/wuxianqiang/promise","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wuxianqiang%2Fpromise","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wuxianqiang%2Fpromise/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wuxianqiang%2Fpromise/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wuxianqiang%2Fpromise/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wuxianqiang","download_url":"https://codeload.github.com/wuxianqiang/promise/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249099609,"owners_count":21212698,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javascript","promise"],"created_at":"2024-08-02T09:01:11.510Z","updated_at":"2025-04-15T15:38:13.394Z","avatar_url":"https://github.com/wuxianqiang.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# promise\n\nPromise对象代表一个异步操作，有三种状态：pending（进行中）、fulfilled（已成功）和rejected（已失败）。\n```js\nfunction Promise(excutor) {\n  let self = this\n  self.status = 'pending'\n  self.value = null\n  self.reason = null\n  function resolve(value) {\n    if (self.status === 'pending') {\n      self.value = value\n      self.status = 'fulfilled'\n    }\n  }\n  function reject(reason) {\n    if (self.status === 'pending') {\n      self.reason = reason\n      self.status = 'rejected'\n    }\n  }\n  try {\n    excutor(resolve, reject)\n  } catch (err) {\n    reject(err)\n  }\n}\n```\nPromise接收一个函数作为参数，该函数有两个参数，一个是resolve，表示成功时执行的函数，一个是reject，表示失败失败时执行的函数。resolve执行时传入的参数会作为then方法中第一个函数的参数，reject执行传入的参数会作为then方法中第二函数的参数。\n```js\nPromise.prototype.then = function (onFulfilled, onRejected) {\n  let self = this\n  if (self.status === 'fulfilled') {\n    onFulfilled(self.value)\n  }\n  if (self.status === 'rejected') {\n    onRejected(self.reason)\n  }\n}\n```\nPromise中常常会写一些异步代码，等到异步操作执行完成才会触发resolve或者reject函数，当执行then方法的时候此时的状态还是初始的pending状态，所以为了能取到值，我们可以通过发布订阅模式来写。\n## 基本调用\n```js\nfunction Promise(excutor) {\n  let self = this\n  self.status = 'pending'\n  self.value = null\n  self.reason = null\n  self.onFulfilledCallbacks = []\n  self.onRejectedCallbacks = []\n  function resolve(value) {\n    if (self.status === 'pending') {\n      self.value = value\n      self.status = 'fulfilled'\n      self.onFulfilledCallbacks.forEach(item =\u003e item(self.value))\n    }\n  }\n  function reject(reason) {\n    if (self.status === 'pending') {\n      self.reason = reason\n      self.status = 'rejected'\n      self.onRejectedCallbacks.forEach(item =\u003e item(self.reason))\n    }\n  }\n  try {\n    excutor(resolve, reject)\n  } catch (err) {\n    reject(err)\n  }\n}\n\n\nPromise.prototype.then = function (onFulfilled, onRejected) {\n  let self = this\n  if (self.status === 'fulfilled') {\n    onFulfilled(self.value)\n  }\n  if (self.status === 'rejected') {\n    onRejected(self.reason)\n  }\n  if (self.status === 'pending') {\n    self.onFulfilledCallbacks.push(onFulfilled)\n    self.onRejectedCallbacks.push(onRejected)\n  }\n}\n```\n我们都知道Promise有一个特点，就是链式调用，当执行then完成后可以继续执行then方法，其实他的原理就是通过返回一个新的Promise实现的，那么then方法中的代码就可以写成下面这样\n```js\nPromise.prototype.then = function (onFulfilled, onRejected) {\n  let self = this\n  if (self.status === 'fulfilled') {\n    return new Promise((resolve, reject) =\u003e {\n      onFulfilled(self.value)\n    })\n  }\n  if (self.status === 'rejected') {\n    return new Promise((resolve, reject) =\u003e {\n      onRejected(self.reason)\n    })\n  }\n  if (self.status === 'pending') {\n    return new Promise((resolve, reject) =\u003e {\n      self.onFulfilledCallbacks.push(onFulfilled)\n      self.onRejectedCallbacks.push(onRejected)\n    })\n  }\n}\n```\nthen方法接收的两个函数中，可以通过return把值传给下一个步，也可以返回一个新的Promise把值传给下一步，then方法执行的时候有个特点，就是为了保证链式调用，上一次then中不管你是成功态还是失败态都会把参数作为下一个then中成功时回调的参数，举个例子\n```js\nlet promise1 = new Promise((resolve, reject) =\u003e {\n  reject('1')\n})\n\nlet promise2 = promise1.then((res) =\u003e {\n  return 1\n}, (err) =\u003e {\n  return 2\n})\npromise2.then((res) =\u003e {\n  console.log(res)//不管上一次then执行的那个回调函数，在这里都可以接收到参数\n})\n```\n## 实现链式调用\n```js\nPromise.prototype.then = function (onFulfilled, onRejected) {\n  let self = this\n  if (self.status === 'fulfilled') {\n    return new Promise((resolve, reject) =\u003e {\n      try {\n        let x = onFulfilled(self.value)\n        if (x instanceof Promise) {\n          x.then(resolve, reject)\n        } else {\n          resolve(x)\n        }\n      } catch (err) {\n        reject(err)\n      }\n    })\n  }\n  if (self.status === 'rejected') {\n    return new Promise((resolve, reject) =\u003e {\n      try {\n        let x = onRejected(self.reason)\n        if (x instanceof Promise) {\n          x.then(resolve, reject)\n        } else {\n          resolve(x)\n        }\n      } catch (err) {\n        reject(err)\n      }\n    })\n  }\n  if (self.status === 'pending') {\n    return new Promise((resolve, reject) =\u003e {\n      self.onFulfilledCallbacks.push(() =\u003e {\n        let x = onFulfilled(self.value)\n        if (x instanceof Promise) {\n          x.then(resolve, reject)\n        } else {\n          resolve(x)\n        }\n      })\n      self.onRejectedCallbacks.push(() =\u003e {\n        let x = onRejected(self.reason)\n        if (x instanceof Promise) {\n          x.then(resolve, reject)\n        } else {\n          resolve(x)\n        }\n      })\n    })\n  }\n}\n```\n上面的代码还要再次处理，就是当某个then中没有传成功时的回调函数或失败时的回调函数，代码就是报错，所以要指定默认值\n```js\nPromise.prototype.then = function (onFulfilled, onRejected) {\n  onFulfilled = typeof onFulfilled === 'function' ? onFulfilled :  function (data) {return data}\n  onRejected = typeof onRejected === 'function' ? onRejected : function (err) {throw err}\n  let self = this\n  if (self.status === 'fulfilled') {\n    return new Promise((resolve, reject) =\u003e {\n      try {\n        let x = onFulfilled(self.value)\n        if (x instanceof Promise) {\n          x.then(resolve, reject)\n        } else {\n          resolve(x)\n        }\n      } catch (err) {\n        reject(err)\n      }\n    })\n  }\n  if (self.status === 'rejected') {\n    return new Promise((resolve, reject) =\u003e {\n      try {\n        let x = onRejected(self.reason)\n        if (x instanceof Promise) {\n          x.then(resolve, reject)\n        } else {\n          resolve(x)\n        }\n      } catch (err) {\n        reject(err)\n      }\n    })\n  }\n  if (self.status === 'pending') {\n    return new Promise((resolve, reject) =\u003e {\n      self.onFulfilledCallbacks.push(() =\u003e {\n        let x = onFulfilled(self.value)\n        if (x instanceof Promise) {\n          x.then(resolve, reject)\n        } else {\n          resolve(x)\n        }\n      })\n      self.onRejectedCallbacks.push(() =\u003e {\n        let x = onRejected(self.reason)\n        if (x instanceof Promise) {\n          x.then(resolve, reject)\n        } else {\n          resolve(x)\n        }\n      })\n    })\n  }\n}\n```\n指定默认值得时候注意失败时要继续抛出错误，因为只有代码报错才会走reject函数\n\n## catch方法\n其实catch方法就是then方法的简写\n```js\nPromise.prototype.catch = function (fn) {\n  return this.then(null, fn)\n}\n```\n## 完整代码\n```js\nfunction Promise(excutor) {\n  let self = this\n  self.status = 'pending'\n  self.value = null\n  self.reason = null\n  self.onFulfilledCallbacks = []\n  self.onRejectedCallbacks = []\n\n  function resolve(value) {\n    if (self.status === 'pending') {\n      self.value = value\n      self.status = 'fulfilled'\n      self.onFulfilledCallbacks.forEach(item =\u003e item())\n    }\n  }\n\n  function reject(reason) {\n    if (self.status === 'pending') {\n      self.reason = reason\n      self.status = 'rejected'\n      self.onRejectedCallbacks.forEach(item =\u003e item())\n    }\n  }\n  try {\n    excutor(resolve, reject)\n  } catch (err) {\n    reject(err)\n  }\n}\n\n\nPromise.prototype.then = function (onFulfilled, onRejected) {\n  onFulfilled = typeof onFulfilled === 'function' ? onFulfilled :  function (data) {resolve(data)}\n  onRejected = typeof onRejected === 'function' ? onRejected : function (err) {throw err}\n  let self = this\n  if (self.status === 'fulfilled') {\n    return new Promise((resolve, reject) =\u003e {\n      try {\n        let x = onFulfilled(self.value)\n        if (x instanceof Promise) {\n          x.then(resolve, reject)\n        } else {\n          resolve(x)\n        }\n      } catch (err) {\n        reject(err)\n      }\n    })\n  }\n  if (self.status === 'rejected') {\n    return new Promise((resolve, reject) =\u003e {\n      try {\n        let x = onRejected(self.reason)\n        if (x instanceof Promise) {\n          x.then(resolve, reject)\n        } else {\n          resolve(x)\n        }\n      } catch (err) {\n        reject(err)\n      }\n    })\n  }\n  if (self.status === 'pending') {\n    return new Promise((resolve, reject) =\u003e {\n      self.onFulfilledCallbacks.push(() =\u003e {\n        let x = onFulfilled(self.value)\n        if (x instanceof Promise) {\n          x.then(resolve, reject)\n        } else {\n          resolve(x)\n        }\n      })\n      self.onRejectedCallbacks.push(() =\u003e {\n        let x = onRejected(self.reason)\n        if (x instanceof Promise) {\n          x.then(resolve, reject)\n        } else {\n          resolve(x)\n        }\n      })\n    })\n  }\n}\n\nPromise.prototype.catch = function (fn) {\n  return this.then(null, fn)\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwuxianqiang%2Fpromise","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwuxianqiang%2Fpromise","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwuxianqiang%2Fpromise/lists"}