缺点:Callback Hell 最大的问题真的不过就是不好写切不好看所衍生出来的不好管理罢了,但是代码却是要给人看给人维护给人管理的啊。于是大家就开始绞尽脑汁想办法
**

实例对象 & 函数对象

  1. function Fn(){ // Fn函数
  2. consol.log(0)
  3. }
  4. let fn = new Fn() // Fn 是构造函数 也是函数对象 本身就是对象 fn是实例对象(简称函数)

01.手写promise全过程

js中进行异步变成的新的解决方案;
语法上是一个构造函数,功能上来说promise对象用来封装一个异步操作并可以获取异步操作的结果;
自己的手写的promise的操作,还差的是promise.all 和promise.race函数

  1. class mypromise {
  2. constructor(extour) {
  3. super(extour)
  4. this.statu = 'pending'
  5. this.value = null
  6. this.taskgroup = []
  7. this._rejected = this._rejected.bind(this)
  8. this._resolved = this._resolved.bind(this)
  9. try {
  10. extour(_resolved, _rejected)
  11. } catch (error) {
  12. this._rejected(error)
  13. }
  14. }
  15. _rejected(value) {
  16. setTimeout(() => {
  17. this.statu = 'reject'
  18. this.value = value
  19. // 如果异步.then 数据先一步执行需要吧异步的数据添加到队列中去
  20. if (this.taskgroup.length > 0) {
  21. this.taskgroup.forEach((_resolved, _rejected) => _rejected(value))
  22. }
  23. })
  24. }
  25. _resolved(value) {
  26. setTimeout(() => {
  27. this.statu = 'fullfilled'
  28. this.value = value
  29. // 如果异步.then 数据先一步执行需要吧异步的数据添加到队列中去
  30. if (this.taskgroup.length > 0) {
  31. this.taskgroup.forEach((_resolved, _rejected) => _resolved(value))
  32. }
  33. })
  34. }
  35. _then(_onresolved, _onrejected) {
  36. // 指定默认传入参数必须为函数
  37. _onresolved = typeof _onresolved === 'function' ? _onresolved : (value) => value
  38. _onrejected = typeof _onrejected === 'function' ? _onrejected : (reason) => { throw reason }
  39. const statuCode = this.statu
  40. return new mypromise((_resolved, _rejected) => {
  41. const hander = function (fun) {
  42. try {
  43. const res = fun()
  44. if (res instanceof mypromise) {
  45. // res._then(_resolved, _rejected)
  46. res._then(() => {
  47. (value) => _resolved(value), (reason) => _rejected(reason)
  48. })
  49. } else {
  50. _resolved(res)
  51. }
  52. } catch (error) {
  53. _rejected(error)
  54. }
  55. }
  56. if (statuCode === 'fullfilled') {
  57. setTimeout(() => {
  58. hander(_onresolved)
  59. })
  60. } else if (statuCode === 'reject') {
  61. setTimeout(() => {
  62. hander(_onrejected)
  63. })
  64. } else {
  65. this.taskgroup.push({
  66. _resolved() {
  67. hander(_onresolved)
  68. },
  69. _rejected() {
  70. hander(_onrejected)
  71. },
  72. })
  73. }
  74. })
  75. }
  76. // 函数只要有错误就报错
  77. _catch(onRejected) {
  78. return this._then(null, onRejected)
  79. }
  80. static _resolved(value) {
  81. // 如果返回值是一个成功的promise 那么返回就是这个 成功的value
  82. // 如果返回值是一个失败的promise 那么返回就是这个reason的reason
  83. return new mypromise((_resolved, _rejected) => {
  84. try {
  85. // 判断返回的value是否是mypromise的实例
  86. if (value instanceof mypromise) {
  87. value._then(_resolved, _rejected)
  88. } else {
  89. // 如果接受一个一般值,那么对于返回的是成功的值;返回的值就是这个一般值
  90. _resolved(value)
  91. }
  92. } catch (error) {
  93. _rejected(error)
  94. }
  95. })
  96. }
  97. static _rejected(reason) {
  98. // 只会返回错误的reason
  99. return new mypromise((_resolved, _rejected) => {
  100. _rejected(reason)
  101. })
  102. }
  103. // 多个异步并行和串行
  104. static all(reason) {
  105. }
  106. static race(promises) {
  107. return new mypromise((_resolved, _rejected) => {
  108. promises.forEach((item)=>{
  109. value = {_resolved(item)},
  110. reason = {_rejected(item)}
  111. })
  112. })
  113. }
  114. }
  115. // 测试
  116. new MyPromise((resolve) => {
  117. setTimeout(() => {
  118. resolve(1);
  119. }, 500);
  120. }).then((res) => {
  121. console.log(res);
  122. return new MyPromise((resolve) => {
  123. setTimeout(() => {
  124. resolve(2);
  125. }, 500);
  126. });
  127. }).then((res) => {
  128. console.log(res);
  129. throw new Error('a error')
  130. }).catch((err) => {
  131. console.log('==>', err);
  132. })

JavaScript 在设计阶段为了保证线程安全并且保证引擎不会被 IO 等待所阻塞导致页面失去响应,于是就向其他 GUI 程序学习了“异步事件模型”,所以“异步事件模型” 是一种解决多线程并行问题的模型。

注】其实所谓的 “异步” 并不是 JavaScript 所独有的,而是一种非常成熟和非常古老的模型,并广泛用用在电子电路的设计上。计算机各种附属 IO 设备,尤其是慢速 IO (比如硬盘),都有异步事件响应的设计的影子。

02.真正消灭 callback 的 generator 和 async/await

03.异步串行 | 异步并行

  1. /**
  2. * 关键点
  3. * 1. new promise 一经创建,立即执行
  4. * 2. 使用 Promise.resolve().then 可以把任务加到微任务队列,防止立即执行迭代方法
  5. * 3. 微任务处理过程中,产生的新的微任务,会在同一事件循环内,追加到微任务队列里
  6. * 4. 使用 race 在某个任务完成时,继续添加任务,保持任务按照最大并发数进行执行
  7. * 5. 任务完成后,需要从 doingTasks 中移出
  8. */
  9. function limit(count, array, iterateFunc) {
  10. const tasks = []
  11. const doingTasks = []
  12. let i = 0
  13. const enqueue = () => {
  14. if (i === array.length) {
  15. return new Promise.resolve()
  16. }
  17. const task = new Promise.resolve().then(() => iterateFunc(array[i++]))
  18. tasks.push(task)
  19. const doing = task.then(() => doingTasks.splice(doingTasks.indexOf(doing), 1))
  20. doingTasks.push(doing)
  21. const res = doingTasks.length >= count ? new Promise.race(doingTasks) : new Promise.resolve()
  22. return res.then(enqueue)
  23. };
  24. return enqueue().then(() => new Promise.all(tasks))
  25. }
  26. // test
  27. const timeout = i => new Promise(resolve => setTimeout(() => resolve(i), i))
  28. limit(2, [1000, 1000, 1000, 1000], timeout).then((res) => {
  29. console.log(res)
  30. })