当前位置:   article > 正文

js实现Promise,call,apply,bind_promise is not callable

promise is not callable

综述:手写一下,加深对知识的理解

1.原生js实现Promise?

  1. // 判断变量否为function
  2. const isFunction = variable => typeof variable === 'function'
  3. // 定义Promise的三种状态常量
  4. const PENDING = 'PENDING'
  5. const FULFILLED = 'FULFILLED'
  6. const REJECTED = 'REJECTED'
  7. class MyPromise {
  8. constructor (handle) {
  9. if (!isFunction(handle)) {
  10. throw new Error('MyPromise must accept a function as a parameter')
  11. }
  12. // 添加状态
  13. this._status = PENDING
  14. // 添加状态
  15. this._value = undefined
  16. // 添加成功回调函数队列
  17. this._fulfilledQueues = []
  18. // 添加失败回调函数队列
  19. this._rejectedQueues = []
  20. // 执行handle
  21. try {
  22. handle(this._resolve.bind(this), this._reject.bind(this))
  23. } catch (err) {
  24. this._reject(err)
  25. }
  26. }
  27. // 添加resovle时执行的函数
  28. _resolve (val) {
  29. const run = () => {
  30. if (this._status !== PENDING) return
  31. // 依次执行成功队列中的函数,并清空队列
  32. const runFulfilled = (value) => {
  33. let cb;
  34. while (cb = this._fulfilledQueues.shift()) {
  35. cb(value)
  36. }
  37. }
  38. // 依次执行失败队列中的函数,并清空队列
  39. const runRejected = (error) => {
  40. let cb;
  41. while (cb = this._rejectedQueues.shift()) {
  42. cb(error)
  43. }
  44. }
  45. /* 如果resolve的参数为Promise对象,则必须等待该Promise对象状态改变后,
  46. 当前Promsie的状态才会改变,且状态取决于参数Promsie对象的状态
  47. */
  48. if (val instanceof MyPromise) {
  49. val.then(value => {
  50. this._value = value
  51. this._status = FULFILLED
  52. runFulfilled(value)
  53. }, err => {
  54. this._value = err
  55. this._status = REJECTED
  56. runRejected(err)
  57. })
  58. } else {
  59. this._value = val
  60. this._status = FULFILLED
  61. runFulfilled(val)
  62. }
  63. }
  64. // 为了支持同步的Promise,这里采用异步调用
  65. setTimeout(run, 0)
  66. }
  67. // 添加reject时执行的函数
  68. _reject (err) {
  69. if (this._status !== PENDING) return
  70. // 依次执行失败队列中的函数,并清空队列
  71. const run = () => {
  72. this._status = REJECTED
  73. this._value = err
  74. let cb;
  75. while (cb = this._rejectedQueues.shift()) {
  76. cb(err)
  77. }
  78. }
  79. // 为了支持同步的Promise,这里采用异步调用
  80. setTimeout(run, 0)
  81. }
  82. // 添加then方法
  83. then (onFulfilled, onRejected) {
  84. const { _value, _status } = this
  85. // 返回一个新的Promise对象
  86. return new MyPromise((onFulfilledNext, onRejectedNext) => {
  87. // 封装一个成功时执行的函数
  88. let fulfilled = value => {
  89. try {
  90. if (!isFunction(onFulfilled)) {
  91. onFulfilledNext(value)
  92. } else {
  93. let res = onFulfilled(value);
  94. if (res instanceof MyPromise) {
  95. // 如果当前回调函数返回MyPromise对象,必须等待其状态改变后在执行下一个回调
  96. res.then(onFulfilledNext, onRejectedNext)
  97. } else {
  98. //否则会将返回结果直接作为参数,传入下一个then的回调函数,并立即执行下一个then的回调函数
  99. onFulfilledNext(res)
  100. }
  101. }
  102. } catch (err) {
  103. // 如果函数执行出错,新的Promise对象的状态为失败
  104. onRejectedNext(err)
  105. }
  106. }
  107. // 封装一个失败时执行的函数
  108. let rejected = error => {
  109. try {
  110. if (!isFunction(onRejected)) {
  111. onRejectedNext(error)
  112. } else {
  113. let res = onRejected(error);
  114. if (res instanceof MyPromise) {
  115. // 如果当前回调函数返回MyPromise对象,必须等待其状态改变后在执行下一个回调
  116. res.then(onFulfilledNext, onRejectedNext)
  117. } else {
  118. //否则会将返回结果直接作为参数,传入下一个then的回调函数,并立即执行下一个then的回调函数
  119. onFulfilledNext(res)
  120. }
  121. }
  122. } catch (err) {
  123. // 如果函数执行出错,新的Promise对象的状态为失败
  124. onRejectedNext(err)
  125. }
  126. }
  127. switch (_status) {
  128. // 当状态为pending时,将then方法回调函数加入执行队列等待执行
  129. case PENDING:
  130. this._fulfilledQueues.push(fulfilled)
  131. this._rejectedQueues.push(rejected)
  132. break
  133. // 当状态已经改变时,立即执行对应的回调函数
  134. case FULFILLED:
  135. fulfilled(_value)
  136. break
  137. case REJECTED:
  138. rejected(_value)
  139. break
  140. }
  141. })
  142. }
  143. // 添加catch方法
  144. catch (onRejected) {
  145. return this.then(undefined, onRejected)
  146. }
  147. // 添加静态resolve方法
  148. static resolve (value) {
  149. // 如果参数是MyPromise实例,直接返回这个实例
  150. if (value instanceof MyPromise) return value
  151. return new MyPromise(resolve => resolve(value))
  152. }
  153. // 添加静态reject方法
  154. static reject (value) {
  155. return new MyPromise((resolve ,reject) => reject(value))
  156. }
  157. // 添加静态all方法
  158. static all (list) {
  159. return new MyPromise((resolve, reject) => {
  160. /**
  161. * 返回值的集合
  162. */
  163. let values = []
  164. let count = 0
  165. for (let [i, p] of list.entries()) {
  166. // 数组参数如果不是MyPromise实例,先调用MyPromise.resolve
  167. this.resolve(p).then(res => {
  168. values[i] = res
  169. count++
  170. // 所有状态都变成fulfilled时返回的MyPromise状态就变成fulfilled
  171. if (count === list.length) resolve(values)
  172. }, err => {
  173. // 有一个被rejected时返回的MyPromise状态就变成rejected
  174. reject(err)
  175. })
  176. }
  177. })
  178. }
  179. // 添加静态race方法
  180. static race (list) {
  181. return new MyPromise((resolve, reject) => {
  182. for (let p of list) {
  183. // 只要有一个实例率先改变状态,新的MyPromise的状态就跟着改变
  184. this.resolve(p).then(res => {
  185. resolve(res)
  186. }, err => {
  187. reject(err)
  188. })
  189. }
  190. })
  191. }
  192. finally (cb) {
  193. return this.then(
  194. value => MyPromise.resolve(cb()).then(() => value),
  195. reason => MyPromise.resolve(cb()).then(() => { throw reason })
  196. );
  197. }
  198. }

2.js实现bind?

  1. Function.prototype.bind = function(oThis) {
  2. if (typeof this !== 'function') {
  3. // closest thing possible to the ECMAScript 5
  4. // internal IsCallable function
  5. throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
  6. }
  7. var aArgs = Array.prototype.slice.call(arguments, 1),
  8. fToBind = this,
  9. // 空函数
  10. fNOP = function() {},
  11. fBound = function() {
  12. return fToBind.apply(this instanceof fNOP
  13. ? this
  14. : oThis,
  15. // 获取调用时(fBound)的传参.bind 返回的函数入参往往是这么传递的
  16. aArgs.concat(Array.prototype.slice.call(arguments)));
  17. };
  18. // 维护原型关系
  19. if (this.prototype) {
  20. // Function.prototype doesn't have a prototype property
  21. fNOP.prototype = this.prototype;
  22. }
  23. fBound.prototype = new fNOP();
  24. return fBound;
  25. };
  26. // 测试
  27. function foo(name) {
  28. this.name = name;
  29. }
  30. var obj = {};
  31. var bar = foo.myBind(obj);
  32. bar('Jack');
  33. console.log(obj.name); // Jack
  34. var alice = new bar('Alice');
  35. console.log(obj.name); // Jack
  36. console.log(alice.name); // Alice

3.js实现call?

  1. function Person (data) {
  2. console.log(data, 'person')
  3. }
  4. function children(data) {
  5. console.log(data,'children')
  6. }
  7. Function.prototype.myCall = function(context, ...args){
  8. if(typeof this !== 'function'){
  9. throw new TypeError(`${this} is not a function`);
  10. }
  11. // 如果没有传或传的值为空对象 context指向window
  12. context = context || window;
  13. context.fn = this;
  14. const result = context.fn(args.join());
  15. delete context.fn; //在使用完之后,删除这个方法
  16. return result; //如果有返回值,将其进行返回
  17. }
  18. Person.myCall(children,77777,8888) //7777,8888

4.js实现apply?

  1. function Person (data) {
  2. console.log(data, 'person')
  3. }
  4. function children(data) {
  5. console.log(data,'children')
  6. }
  7. Function.prototype.myApply = function(context, args){
  8. if(typeof this !== 'function'){
  9. throw new TypeError(`${this} is not a function`);
  10. }
  11. if(!Array.isArray(args)){
  12. throw new TypeError(`${args} is not a Array`);
  13. }
  14. context = context || window;
  15. context.fn = this;
  16. const result = context.fn(args);
  17. delete context.fn;
  18. return result;
  19. }
  20. Person.myApply(children,[77777,8888])

 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/388465
推荐阅读
相关标签
  

闽ICP备14008679号