Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。

Promise三种状态

  • pending: 初始状态,既不是成功,也不是失败状态。
  • fulfilled: 意味着操作成功完成。
  • rejected: 意味着操作失败。

    Promise.resolve Promise.reject

  • 返回成功和失败的promise状态

不要在解析为自身的thenable 上调用Promise.resolve。这将导致无限递归,因为它试图展平无限嵌套的promise
Promise.all(iterable)
这个方法返回一个新的promise对象,该promise对象在iterable参数对象里所有的promise对象都成功的时候才会触发成功,一旦有任何一个iterable里面的promise对象失败则立即触发该promise对象的失败。这个新的promise对象在触发成功状态以后,会把一个包含iterable里所有promise返回值的数组作为成功回调的返回值,顺序跟iterable的顺序保持一致;如果这个新的promise对象触发了失败状态,它会把iterable里第一个触发失败的promise对象的错误信息作为它的失败错误信息。Promise.all方法常被用于处理多个promise对象的状态集合。
Promise.race(iterable)当iterable参数里的任意一个子promise被成功或失败后,父promise马上也会用子promise的成功返回值或失败详情作为参数调用父promise绑定的相应句柄,并返回该promise对象。

手写Promise

基础版

  1. //没有解决链式调用和细节问题
  2. class MyPromise {
  3. constructor(fn) {
  4. //默认状态
  5. this.status = "pendding";
  6. //成功状态
  7. this.value = undefined;
  8. //失败状态
  9. this.reason = undefined;
  10. // 成功存放的数组
  11. this.onResolvedCallbacks = [];
  12. // 失败存放法数组
  13. this.onRejectedCallbacks = [];
  14. try {
  15. fn(this.resolve.bind(this), this.reject.bind(this));
  16. } catch (err) {
  17. console.log(err)
  18. this.reject(err);
  19. }
  20. }
  21. resolve(value) {
  22. if (this.status === "pendding") {
  23. this.value = value
  24. this.status = "resolve"
  25. this.onResolvedCallbacks.forEach(fn=>fn())
  26. }
  27. }
  28. reject(reason) {
  29. if (this.status === "pendding") {
  30. this.reason = reason
  31. this.status = "reject"
  32. this.onRejectedCallbacks.forEach(fn=>fn)
  33. }
  34. }
  35. then(onFulfilled, onRejected) {
  36. if (this.status === 'resolve') onFulfilled(this.value);
  37. if (this.status === 'reject') onRejected(this.reason)
  38. if (this.status === 'pendding') {
  39. this.onResolvedCallbacks.push(() => {onFulfilled(this.value)})
  40. if(onRejected) this.onRejectedCallbacks.push(() => onRejected(this.reason))
  41. }
  42. }
  43. }

进阶

  1. class Promise{
  2. constructor(executor){
  3. this.state = 'pending';
  4. this.value = undefined;
  5. this.reason = undefined;
  6. this.onResolvedCallbacks = [];
  7. this.onRejectedCallbacks = [];
  8. let resolve = value => {
  9. if (this.state === 'pending') {
  10. this.state = 'fulfilled';
  11. this.value = value;
  12. this.onResolvedCallbacks.forEach(fn=>fn());
  13. }
  14. };
  15. let reject = reason => {
  16. if (this.state === 'pending') {
  17. this.state = 'rejected';
  18. this.reason = reason;
  19. this.onRejectedCallbacks.forEach(fn=>fn());
  20. }
  21. };
  22. try{
  23. executor(resolve, reject);
  24. } catch (err) {
  25. reject(err);
  26. }
  27. }
  28. then(onFulfilled,onRejected) {
  29. onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
  30. onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };
  31. let promise2 = new Promise((resolve, reject) => {
  32. if (this.state === 'fulfilled') {
  33. setTimeout(() => {
  34. try {
  35. let x = onFulfilled(this.value);
  36. resolvePromise(promise2, x, resolve, reject);
  37. } catch (e) {
  38. reject(e);
  39. }
  40. }, 0);
  41. };
  42. if (this.state === 'rejected') {
  43. setTimeout(() => {
  44. try {
  45. let x = onRejected(this.reason);
  46. resolvePromise(promise2, x, resolve, reject);
  47. } catch (e) {
  48. reject(e);
  49. }
  50. }, 0);
  51. };
  52. if (this.state === 'pending') {
  53. this.onResolvedCallbacks.push(() => {
  54. setTimeout(() => {
  55. try {
  56. let x = onFulfilled(this.value);
  57. resolvePromise(promise2, x, resolve, reject);
  58. } catch (e) {
  59. reject(e);
  60. }
  61. }, 0);
  62. });
  63. this.onRejectedCallbacks.push(() => {
  64. setTimeout(() => {
  65. try {
  66. let x = onRejected(this.reason);
  67. resolvePromise(promise2, x, resolve, reject);
  68. } catch (e) {
  69. reject(e);
  70. }
  71. }, 0)
  72. });
  73. };
  74. });
  75. return promise2;
  76. }
  77. catch(fn){
  78. return this.then(null,fn);
  79. }
  80. }
  81. function resolvePromise(promise2, x, resolve, reject){
  82. if(x === promise2){
  83. return reject(new TypeError('Chaining cycle detected for promise'));
  84. }
  85. let called;
  86. if (x != null && (typeof x === 'object' || typeof x === 'function')) {
  87. try {
  88. let then = x.then;
  89. if (typeof then === 'function') {
  90. then.call(x, y => {
  91. if(called)return;
  92. called = true;
  93. resolvePromise(promise2, y, resolve, reject);
  94. }, err => {
  95. if(called)return;
  96. called = true;
  97. reject(err);
  98. })
  99. } else {
  100. resolve(x);
  101. }
  102. } catch (e) {
  103. if(called)return;
  104. called = true;
  105. reject(e);
  106. }
  107. } else {
  108. resolve(x);
  109. }
  110. }
  111. //resolve方法
  112. Promise.resolve = function(val){
  113. return new Promise((resolve,reject)=>{
  114. resolve(val)
  115. });
  116. }
  117. //reject方法
  118. Promise.reject = function(val){
  119. return new Promise((resolve,reject)=>{
  120. reject(val)
  121. });
  122. }
  123. //race方法
  124. Promise.race = function(promises){
  125. return new Promise((resolve,reject)=>{
  126. for(let i=0;i<promises.length;i++){
  127. promises[i].then(resolve,reject)
  128. };
  129. })
  130. }
  131. //all方法(获取所有的promise,都执行then,把结果放到数组,一起返回)
  132. Promise.all = function(promises){
  133. let arr = [];
  134. let i = 0;
  135. function processData(index,data){
  136. arr[index] = data;
  137. i++;
  138. if(i == promises.length){
  139. resolve(arr);
  140. };
  141. };
  142. return new Promise((resolve,reject)=>{
  143. for(let i=0;i<promises.length;i++){
  144. promises[i].then(data=>{
  145. processData(i,data);
  146. },reject);
  147. };
  148. });
  149. }