Promise

类式实现

  1. class MyPromise {
  2. constructor(executor) {
  3. this.state = 'pending'; // resolved rejected
  4. this.value = null;
  5. this.fns = [];
  6. const resolve = (val) => {
  7. if (this.state === 'pending') {
  8. this.state = 'resolved';
  9. this.value = val;
  10. this.fns.forEach(({ resolveFn }) => resolveFn(val));
  11. }
  12. };
  13. const reject = (reason) => {
  14. if (this.state === 'pending') {
  15. this.state = 'rejected';
  16. this.value = reason;
  17. this.fns.forEach(({ rejectFn }) => rejectFn(reason));
  18. }
  19. };
  20. try {
  21. executor(resolve, reject);
  22. } catch (err) {
  23. reject(err);
  24. }
  25. }
  26. then(resolveFn, rejectFn) {
  27. if (typeof resolveFn !== 'function') {
  28. resolveFn = (value) => value;
  29. }
  30. if (typeof rejectFn !== 'function') {
  31. rejectFn = (reason) => {
  32. throw new Error(reason);
  33. };
  34. }
  35. return new MyPromise((resolve, reject) => {
  36. const handle = (method) => {
  37. try {
  38. const result = method(this.value); // 获取调用返回结果
  39. // 判断这个结果是不是promise的实例,是则调用这个promise然后传入resolve,reject
  40. if (result instanceof MyPromise) {
  41. result.then(resolve, reject);
  42. } else {
  43. // 如果不是promise,就直接变成成功的值
  44. resolve(result); // 直接存起来
  45. }
  46. // 如果上面执行的有抛出异常,则表明出现错误,直接调用reject
  47. } catch (error) {
  48. reject(error);
  49. }
  50. };
  51. if (this.state === 'resolved') {
  52. handle(resolveFn);
  53. } else if (this.state === 'rejected') {
  54. handle(rejectFn);
  55. } else {
  56. this.fns.push({
  57. resolveFn() {
  58. handle(resolveFn);
  59. },
  60. rejectFn() {
  61. handle(rejectFn);
  62. },
  63. });
  64. }
  65. });
  66. }
  67. catch(rejectFn) {
  68. return this.then(undefined, rejectFn);
  69. }
  70. finally(callback) {
  71. return this.then(
  72. (value) => MyPromise.resolve(callback()).then(() => value),
  73. (reason) => MyPromise.reject(callback()).then(() => reason)
  74. );
  75. }
  76. static resolve(value) {
  77. return new MyPromise((resolve, reject) => {
  78. if (value instanceof MyPromise) {
  79. value.then(resolve, reject);
  80. } else {
  81. resolve(value);
  82. }
  83. });
  84. }
  85. static reject(reason) {
  86. return new MyPromise((resolve, reject) => {
  87. reject(value);
  88. });
  89. }
  90. }
  1. class MyPromise {
  2. constructor(executor) { // executor执行器
  3. this.status = 'pending' // 等待状态
  4. this.value = null // 成功或失败的参数
  5. this.fulfilledCallbacks = [] // 成功的函数队列
  6. this.rejectedCallbacks = [] // 失败的函数队列
  7. const that = this
  8. function resolve(value) { // 成功的方法
  9. if (that.status === 'pending') {
  10. that.status = 'resolved'
  11. that.value = value
  12. that.fulfilledCallbacks.forEach(myFn => myFn(that.value)) //执行回调方法
  13. }
  14. }
  15. function reject(value) { //失败的方法
  16. if (that.status === 'pending') {
  17. that.status = 'rejected'
  18. that.value = value
  19. that.rejectedCallbacks.forEach(myFn => myFn(that.value)) //执行回调方法
  20. }
  21. }
  22. try {
  23. executor(resolve, reject)
  24. } catch (err) {
  25. reject(err)
  26. }
  27. }
  28. then(onFulfilled, onRejected) {
  29. if (this.status === 'pending') {
  30. // 等待状态,添加回调函数到成功的函数队列
  31. this.fulfilledCallbacks.push(() => {
  32. onFulfilled(this.value)
  33. })
  34. // 等待状态,添加回调函数到失败的函数队列
  35. this.rejectedCallbacks.push(() => {
  36. onRejected(this.value)
  37. })
  38. }
  39. if (this.status === 'resolved') { // 支持同步调用
  40. console.log('this', this)
  41. onFulfilled(this.value)
  42. }
  43. if (this.status === 'rejected') { // 支持同步调用
  44. onRejected(this.value)
  45. }
  46. }
  47. }
  48. // 测试
  49. function fn() {
  50. return new MyPromise((resolve, reject) => {
  51. setTimeout(() => {
  52. if(Math.random() > 0.6) {
  53. resolve(1)
  54. } else {
  55. reject(2)
  56. }
  57. }, 1000)
  58. })
  59. }
  60. fn().then(
  61. res => {
  62. console.log('res', res) // res 1
  63. },
  64. err => {
  65. console.log('err', err) // err 2
  66. })

方法实现

  1. /**
  2. * Promise构造函数
  3. * executor: 内部同步执行的函数(resolve, reject) => {}
  4. * new Promise((resolve, reject) => {
  5. * setTimeout(() => { resolve(42); }, 1000);
  6. * })
  7. */
  8. function Promise2(executor) {
  9. // 初始状态
  10. this.PromiseState = "pending";
  11. // 初始结果
  12. this.PromiseResult = null;
  13. // 保存回调函数
  14. this.callbacks = [];
  15. const self = this;
  16. // resolve函数
  17. function resolve(value) {
  18. // 判断状态,让Promise对象只能修改一次
  19. if(self.PromiseState !== "pending") return;
  20. // 修改状态
  21. self.PromiseState = "fulfilled";
  22. // 修改结果
  23. self.PromiseResult = value;
  24. // 调用回调函数
  25. setTimeout(() => {
  26. self.callbacks.forEach(element => {
  27. element.onResolved(value);
  28. });
  29. });
  30. }
  31. // reject函数
  32. function reject(reason) {
  33. // 判断状态,让Promise对象只能修改一次
  34. if(self.PromiseState !== "pending") return;
  35. // 修改状态
  36. self.PromiseState = "rejected";
  37. // 修改结果
  38. self.PromiseResult = reason;
  39. // 调用回调函数
  40. setTimeout(() => {
  41. self.callbacks.forEach(element => {
  42. element.onRejected(reason);
  43. });
  44. });
  45. }
  46. // 同步调用执行器函数
  47. try {
  48. executor(resolve, reject);
  49. } catch (error) {
  50. reject(error);
  51. }
  52. }
  53. Promise2.prototype.then = function(onResolved, onRejected) {
  54. if(typeof onResolved !== "function") {
  55. onResolved = value => value;
  56. }
  57. if(typeof onRejected !== "function") {
  58. onRejected = reason => {
  59. throw new Error(reason);
  60. }
  61. }
  62. // 固定返回一个Promise对象,这里我们称为newPro对象,供下一环节使用
  63. // 注意这里是箭头函数,所以里面this指向oldPro对象(最初创建的Promise对象,称为oldPro)
  64. return new Promise2((resolve, reject) => {
  65. function handle(callback) {
  66. try {
  67. let result = callback(this.PromiseResult);
  68. // 当result为Promise对象,这里我们称为resultPro,这个resultPro是外部自定义的
  69. if(result instanceof Promise) {
  70. // then方法将v函数压入resultPro对象的callbacks数组里,
  71. // 当resultPro对象执行resolve函数时触发callbacks数组执行v函数,
  72. // 执行v函数触发newPro对象的resolve函数,继而触发下一环节Promise对象执行onResolved函数
  73. result.then(
  74. // 该onResolved函数这里我们称为v函数,参数值为resultPro对象执行resolve函数时传入的值
  75. v => {
  76. // resolve为Promise构造函数内置函数
  77. resolve(v);
  78. },
  79. r => {
  80. reject(r);
  81. }
  82. );
  83. } else {
  84. // 触发newPro对象的resolve函数,并将result值向下一环节Promise对象的onResolved函数传递
  85. resolve(result);
  86. }
  87. } catch (error) {
  88. reject(error);
  89. }
  90. }
  91. if(this.PromiseState === "pending") {
  92. // 将then方法的onResolved函数压入oldPro对象的callbacks数组,供oldPro执行resolve方法调用
  93. this.callbacks.push({
  94. onResolved: (value) => {
  95. handle.call(this, onResolved);
  96. },
  97. onRejected (reason) {
  98. handle.call(this, onRejected);
  99. }
  100. });
  101. }
  102. if(this.PromiseState === "fulfilled") {
  103. setTimeout(() => {
  104. handle(onResolved);
  105. })
  106. }
  107. if(this.PromiseState === "rejected") {
  108. setTimeout(() => {
  109. handle(onRejected);
  110. })
  111. }
  112. });
  113. }

其他

  1. function MyPromise(executor) {
  2. var self = this;
  3. self.status = 'pending'
  4. self.value = undefined
  5. self.reason = undefined
  6. self.onResolved = []
  7. self.onRejected = []
  8. function resolve(value) {
  9. if (self.status === 'pending') {
  10. self.status = 'fulfilled'
  11. self.value = value
  12. self.onResolved.forEach(fn => fn())
  13. }
  14. }
  15. function reject(reason) {
  16. if (self.status === 'pending') {
  17. self.reason = reason
  18. self.status = 'rejected'
  19. self.onRejected.forEach(fn => fn())
  20. }
  21. }
  22. // executor(resolve, reject)
  23. try {
  24. executor(resolve, reject)
  25. }catch(e) {
  26. reject(e)
  27. }
  28. }
  29. MyPromise.prototype.then = function(onfulfilled, onrejected) {
  30. let self = this
  31. if (self.status === 'fulfilled') {
  32. onfulfilled(self.value)
  33. }
  34. if (self.status === 'rejected') {
  35. onrejected(self.reason)
  36. }
  37. if (self.status === 'pending') {
  38. self.onResolved.push(function() {
  39. onfulfilled(self.value)
  40. })
  41. self.onRejected.push(function() {
  42. onfulfilled(self.reason)
  43. })
  44. }
  45. }
  46. var p = new MyPromise((resolve, reject) => {
  47. setTimeout(() => {
  48. resolve(111);
  49. }, 1000);
  50. })
  51. p.then((value) => {
  52. console.log(value)
  53. }, (reason) => {
  54. console.log('err', reason);
  55. })

Promise.all() 方法

  1. 接收一个Promise 实例的数组或具有 Iterator 接口的对象作为参数
  2. 这个方法返回一个新的 Promise 对象
  3. 遍传入的参数,用 Promise.resolve() 将参数”包一层”,使其变成一个 Promise 对象
  4. 参数所有回调成功才是成功,返回值数组与参数顺序一致
  5. 参数数组其中一个失败,则触发失败状态,第一个触发失败的 Promise 错误信息作为 Promise.all的错误信息

实现:

  1. function promiseAll (promises){
  2. return new Promise(function(resolve, reject) {
  3. if(!Array.isArray(promises)) {
  4. throw new TypeError('argumenbt must be an array')
  5. }
  6. var resolvedCounter = 0;
  7. var promiseNum = promises.length;
  8. var resolvedResult = [];
  9. for(let i = 0; i < promiseNum; i++) {
  10. Promise.resolve(promises[i]).then(value => {
  11. resolvedCounter++;
  12. resolvedResult[i] = value;
  13. if(resolvedCounter === promiseNum) {
  14. return resolve(resolvedResult);
  15. }
  16. }, error => {
  17. return reject(error)
  18. })
  19. }
  20. })
  21. }

测试:

  1. // ok
  2. let p1 = new Promise(function(resolve, reject) {
  3. setTimeout(function() {
  4. resolve(1);
  5. }, 1000)
  6. })
  7. let p2 = new Promise(function(resolve, reject) {
  8. setTimeout(function() {
  9. resolve(2);
  10. }, 2000)
  11. })
  12. let p3 = new Promise(function(resolve, reject) {
  13. setTimeout(function() {
  14. resolve(3);
  15. }, 3000)
  16. })
  17. promiseAll([p1, p2, p3]).then(res => {
  18. console.log(res); // [1, 2, 3]
  19. })
  20. // error
  21. let p1 = new Promise(function(resolve, reject) {
  22. setTimeout(function() {
  23. resolve(1);
  24. }, 1000)
  25. })
  26. let p2 = new Promise(function(resolve, reject) {
  27. setTimeout(function() {
  28. reject(2);
  29. }, 2000)
  30. })
  31. let p3 = new Promise(function(resolve, reject) {
  32. setTimeout(function() {
  33. resolve(3);
  34. }, 3000)
  35. })
  36. promiseAll([p1, p2, p3]).catch(err => {
  37. console.log(err) // 2
  38. })

Promise.resolve

Promsie.resolve(value) 可以将任何值转成值为 value 状态是 fulfilled 的 Promise,但如果传入的值本身是 Promise 则会原样返回它。

  1. Promise.resolve = function(value) {
  2. // 如果是 Promsie,则直接输出它
  3. if(value instanceof Promise){
  4. return value
  5. }
  6. return new Promise(resolve => resolve(value))
  7. }

Promise.reject

和 Promise.resolve() 类似,Promise.reject() 会实例化一个 rejected 状态的 Promise。但与 Promise.resolve() 不同的是,如果给 Promise.reject() 传递一个 Promise 对象,则这个对象会成为新 Promise 的值。

  1. Promise.reject = function(reason) {
  2. return new Promise((resolve, reject) => reject(reason))
  3. }

Promise.all

Promise.all 的规则是这样的:

  • 传入的所有 Promsie 都是 fulfilled,则返回由他们的值组成的,状态为 fulfilled 的新 Promise;
  • 只要有一个 Promise 是 rejected,则返回 rejected 状态的新 Promsie,且它的值是第一个 rejected 的 Promise 的值;
  • 只要有一个 Promise 是 pending,则返回一个 pending 状态的新 Promise;
  1. /**
  2. * Promise.all Promise进行并行处理
  3. * 参数: promise对象组成的数组作为参数
  4. * 返回值: 返回一个Promise实例
  5. * 当这个数组里的所有promise对象全部进入FulFilled状态的时候,才会resolve。
  6. */
  7. Promise.all = function(promises) {
  8. return new Promise((resolve, reject) => {
  9. let values = []
  10. let count = 0
  11. promises.forEach((promise, index) => {
  12. promise.then(value => {
  13. console.log('value:', value, 'index:', index)
  14. values[index] = value
  15. count++
  16. if (count === promises.length) {
  17. resolve(values)
  18. }
  19. }, reject)
  20. })
  21. })
  22. }
  23. // or
  24. function PromiseAll(promises){
  25. return new Promise((resolve, reject)=>{
  26. if(!Array.isArray(promises)){
  27. throw new TypeError("promises must be an array")
  28. }
  29. let result = []
  30. let count = 0
  31. promises.forEach((promise, index) => {
  32. promise.then((res)=>{
  33. result[index] = res
  34. count++
  35. count === promises.length && resolve(result)
  36. }, (err)=>{
  37. reject(err)
  38. })
  39. })
  40. })
  41. }

Promise.race

Promise.race 会返回一个由所有可迭代实例中第一个 fulfilled 或 rejected 的实例包装后的新实例。

  1. /**
  2. * Promise.race
  3. * 参数: 接收 promise对象组成的数组作为参数
  4. * 返回值: 返回一个Promise实例
  5. * 只要有一个promise对象进入 FulFilled 或者 Rejected 状态的话,就会继续进行后面的处理(取决于哪一个更快)
  6. */
  7. Promise.race = function(promises) {
  8. return new Promise((resolve, reject) => {
  9. promises.forEach((promise) => {
  10. promise.then(resolve, reject);
  11. });
  12. });
  13. }
  14. // or
  15. Promise.race = function(promiseArr) {
  16. return new Promise((resolve, reject) => {
  17. promiseArr.forEach(p => {
  18. Promise.resolve(p).then(val => {
  19. resolve(val)
  20. }, err => {
  21. rejecte(err)
  22. })
  23. })
  24. })
  25. }

Promise.allSettled

Promise.allSettled 的规则是这样:

  • 所有 Promise 的状态都变化了,那么新返回一个状态是 fulfilled 的 Promise,且它的值是一个数组,数组的每项由所有 Promise 的值和状态组成的对象;
  • 如果有一个是 pending 的 Promise,则返回一个状态是 pending 的新实例;
  1. Promise.allSettled = function(promiseArr) {
  2. let result = []
  3. return new Promise((resolve, reject) => {
  4. promiseArr.forEach((p, i) => {
  5. Promise.resolve(p).then(val => {
  6. result.push({
  7. status: 'fulfilled',
  8. value: val
  9. })
  10. if (result.length === promiseArr.length) {
  11. resolve(result)
  12. }
  13. }, err => {
  14. result.push({
  15. status: 'rejected',
  16. reason: err
  17. })
  18. if (result.length === promiseArr.length) {
  19. resolve(result)
  20. }
  21. })
  22. })
  23. })
  24. }

Promise.any

Promise.any 的规则是这样:

  • 空数组或者所有 Promise 都是 rejected,则返回状态是 rejected 的新 Promsie,且值为 AggregateError 的错误;
  • 只要有一个是 fulfilled 状态的,则返回第一个是 fulfilled 的新实例;
  • 其他情况都会返回一个 pending 的新实例;
  1. Promise.any = function(promiseArr) {
  2. let index = 0
  3. return new Promise((resolve, reject) => {
  4. if (promiseArr.length === 0) return
  5. promiseArr.forEach((p, i) => {
  6. Promise.resolve(p).then(val => {
  7. resolve(val)
  8. }, err => {
  9. index++
  10. if (index === promiseArr.length) {
  11. reject(new AggregateError('All promises were rejected'))
  12. }
  13. })
  14. })
  15. })
  16. }

Promise.finally

接收一个回调函数, 但无参数接收 无论成功失败状态, 都会执行finally

  1. Promise.prototype.finally = function (callback) {
  2. let P = this.constructor; // P===Promise
  3. return this.then(
  4. value => P.resolve(callback()).then(() => value),
  5. reason => P.resolve(callback()).then(() => { throw reason })
  6. );
  7. };
  8. // or
  9. Promise.prototype.finally = function (cb) {
  10. return this.then(function (value) {
  11. return Promise.resolve(cb()).then(function () {
  12. return value
  13. })
  14. }, function (err) {
  15. return Promise.resolve(cb()).then(function () {
  16. throw err
  17. })
  18. })
  19. }

await 实现

实现

  1. function run(gen) {
  2. return new Promise((resolve, reject) => {
  3. const g = gen();
  4. function _next(value) {
  5. let res; // 存储结果
  6. try {
  7. res = g.next(value);
  8. } catch (error) {
  9. reject(error);
  10. }
  11. if (res.deno) {
  12. // 执行结束了
  13. return resolve(res.value); // 结束
  14. }
  15. Promise.resolve(res.value).then(
  16. (newVal) => {
  17. _next(newVal);
  18. },
  19. (err) => g.throw(err)
  20. ); // 不然给人家自己处理错误
  21. }
  22. _next();
  23. });
  24. }
  25. function* myGenerator() {
  26. try {
  27. const val1 = yield Promise.resolve('这是值1');
  28. console.log(val1);
  29. const val2 = yield '这是值2';
  30. console.log(val2);
  31. yield Promise.reject('开始产生错误');
  32. // 不执行了
  33. const val3 = yield '这是值3';
  34. console.log(val3);
  35. } catch (error) {
  36. console.log('错误打印', error);
  37. }
  38. }
  39. run(myGenerator);


手写async /await(generator的语法糖)

前提说明

  1. const getData =
  2. () => new Promise(
  3. resolve => setTimeout(() => resolve("data"), 1000)
  4. )
  5. async function test() {
  6. const data = await getData()
  7. console.log('data: ', data);
  8. const data2 = await getData()
  9. console.log('data2: ', data2);
  10. return 'success'
  11. }
  12. // 这样的一个函数 应该再1秒后打印data 再过一秒打印data2 同时打印success
  13. test().then(res => console.log(res))

思路

  1. function* testG() {
  2. // await被编译成了yield
  3. const data = yield getData()
  4. console.log('data: ', data);
  5. const data2 = yield getData()
  6. console.log('data2: ', data2);
  7. return 'success'
  8. }
  9. 我们知道,generator函数是不会自动执行的,每一次调用它的next方法,会停留在下一个yield的位置。
  10. 利用这个特性,我们只要编写一个自动执行的函数,就可以让这个generator函数完全实现async函数的功能。
  11. const getData = () => new Promise(resolve => setTimeout(() => resolve("data"), 1000))
  12. var test = asyncToGenerator(
  13. function* testG() {
  14. // await被编译成了yield
  15. const data = yield getData()
  16. console.log('data: ', data);
  17. const data2 = yield getData()
  18. console.log('data2: ', data2);
  19. return 'success'
  20. }
  21. )
  22. test().then(res => console.log(res))

实现

asyncToGenerator接受一个generator函数,返回一个promise, 关键就在于,里面用yield来划分的异步流程,应该如何自动执行。

如果是手动执行

  1. 在编写这个函数之前,我们先模拟手动去调用这个generator函数去一步步的把流程走完,有助于后面的思考。
  2. function* testG() {
  3. // await被编译成了yield
  4. const data = yield getData()
  5. console.log('data: ', data);
  6. const data2 = yield getData()
  7. console.log('data2: ', data2);
  8. return 'success'
  9. }
  10. 我们先调用testG生成一个迭代器
  11. // 返回了一个迭代器
  12. var gen = testG()
  13. 然后开始执行第一次next
  14. // 第一次调用next 停留在第一个yield的位置
  15. // 返回的promise里 包含了data需要的数据
  16. var dataPromise = gen.next()
  17. 这段代码要切割成左右两部分来看,第一次调用next,其实只是停留在了yield getData()这里,
  18. data的值并没有被确定。
  19. 那么什么时候data的值会被确定呢?
  20. 下一次调用next的时候,传的参数会被作为上一个yield前面接受的值
  21. 也就是说,我们再次调用gen.next('这个参数才会被赋给data变量')的时候
  22. data的值才会被确定为'这个参数才会被赋给data变量
  23. gen.next('这个参数才会被赋给data变量')
  24. // 然后这里的data才有值
  25. const data = yield getData()
  26. // 然后打印出data
  27. console.log('data: ', data);
  28. // 然后继续走到下一个yield
  29. const data2 = yield getData()
  30. 然后往下执行,直到遇到下一个yield,继续这样的流程...
  31. 这是generator函数设计的一个比较难理解的点,但是为了实现我们的目标,还是得去学习它~
  32. 借助这个特性,如果我们这样去控制yield的流程,是不是就能实现异步串行了?
  33. function* testG() {
  34. // await被编译成了yield
  35. const data = yield getData()
  36. console.log('data: ', data);
  37. const data2 = yield getData()
  38. console.log('data2: ', data2);
  39. return 'success'
  40. }
  41. var gen = testG()
  42. var dataPromise = gen.next()
  43. dataPromise.then((value1) => {
  44. // data1的value被拿到了 继续调用next并且传递给data
  45. var data2Promise = gen.next(value1)
  46. // console.log('data: ', data);
  47. // 此时就会打印出data
  48. data2Promise.value.then((value2) => {
  49. // data2的value拿到了 继续调用next并且传递value2
  50. gen.next(value2)
  51. // console.log('data2: ', data2);
  52. // 此时就会打印出data2
  53. })
  54. })

手写实现

  1. // 正式版
  2. function asyncToGenerator(generatorFunc) {
  3. return function() {
  4. const gen = generatorFunc.apply(this, arguments)
  5. return new Promise((resolve, reject) => {
  6. function step(key, arg) {
  7. let generatorResult
  8. try {
  9. generatorResult = gen[key](arg "key")
  10. } catch (error) {
  11. return reject(error)
  12. }
  13. const { value, done } = generatorResult
  14. if (done) {
  15. return resolve(value)
  16. } else {
  17. return Promise.resolve(value).then(val => step('next', val), err => step('throw', err))
  18. }
  19. }
  20. step("next")
  21. })
  22. }
  23. }
  24. // 导演剪辑版
  25. function asyncToGenerator(generatorFunc) {
  26. // 返回的是一个新的函数
  27. return function() {
  28. // 先调用generator函数 生成迭代器
  29. // 对应 var gen = testG()
  30. const gen = generatorFunc.apply(this, arguments)
  31. // 返回一个promise 因为外部是用.then的方式 或者await的方式去使用这个函数的返回值的
  32. // var test = asyncToGenerator(testG)
  33. // test().then(res => console.log(res))
  34. return new Promise((resolve, reject) => {
  35. // 内部定义一个step函数 用来一步一步的跨过yield的阻碍
  36. // key有next和throw两种取值,分别对应了gen的next和throw方法
  37. // arg参数则是用来把promise resolve出来的值交给下一个yield
  38. function step(key, arg) {
  39. let generatorResult
  40. // 这个方法需要包裹在try catch中
  41. // 如果报错了 就把promise给reject掉 外部通过.catch可以获取到错误
  42. try {
  43. generatorResult = gen[key](arg)
  44. } catch (error) {
  45. return reject(error)
  46. }
  47. // gen.next() 得到的结果是一个 { value, done } 的结构
  48. const { value, done } = generatorResult
  49. if (done) {
  50. // 如果已经完成了 就直接resolve这个promise
  51. // 这个done是在最后一次调用next后才会为true
  52. // 以本文的例子来说 此时的结果是 { done: true, value: 'success' }
  53. // 这个value也就是generator函数最后的返回值
  54. return resolve(value)
  55. } else {
  56. // 除了最后结束的时候外,每次调用gen.next()
  57. // 其实是返回 { value: Promise, done: false } 的结构,
  58. // 这里要注意的是Promise.resolve可以接受一个promise为参数
  59. // 并且这个promise参数被resolve的时候,这个then才会被调用
  60. return Promise.resolve(
  61. // 这个value对应的是yield后面的promise
  62. value
  63. ).then(
  64. // value这个promise被resove的时候,就会执行next
  65. // 并且只要done不是true的时候 就会递归的往下解开promise
  66. // 对应gen.next().value.then(value => {
  67. // gen.next(value).value.then(value2 => {
  68. // gen.next()
  69. //
  70. // // 此时done为true了 整个promise被resolve了
  71. // // 最外部的test().then(res => console.log(res))的then就开始执行了
  72. // })
  73. // })
  74. function onResolve(val) {
  75. step("next", val)
  76. },
  77. // 如果promise被reject了 就再次进入step函数
  78. // 不同的是,这次的try catch中调用的是gen.throw(err)
  79. // 那么自然就被catch到 然后把promise给reject掉啦
  80. function onReject(err) {
  81. step("throw", err)
  82. },
  83. )
  84. }
  85. }
  86. step("next")
  87. })
  88. }
  89. }

实现限制并发的Promise调度器

JS实现一个带并发限制的异步调度器Scheduler, 保证同时运行的任务最多有两个

  1. ## 题目
  2. ```js
  3. addTask(1000,"1");
  4. addTask(500,"2");
  5. addTask(300,"3");
  6. addTask(400,"4");
  7. 的输出顺序是:2 3 1 4
  8. 整个的完整执行流程:
  9. 一开始1、2两个任务开始执行
  10. 500ms时,2任务执行完毕,输出2,任务3开始执行
  11. 800ms时,3任务执行完毕,输出3,任务4开始执行
  12. 1000ms时,1任务执行完毕,输出1,此时只剩下4任务在执行
  13. 1200ms时,4任务执行完毕,输出4

书写

  1. class Scheduler {
  2. constructor(limit) {
  3. this.queue = []
  4. this.limit = limit
  5. this.count = 0
  6. }
  7. add(time, order) {
  8. const promiseCreator = () => {
  9. return new Promise((resolve, reject) => {
  10. setTimeout(() => {
  11. console.log(order)
  12. resolve()
  13. }, time)
  14. })
  15. }
  16. this.queue.push(promiseCreator)
  17. }
  18. taskStart() {
  19. for(let i = 0; i < this.limit; i++) {
  20. this.request()
  21. }
  22. }
  23. request() {
  24. if (!this.queue.length || this.count >= this.limit) return
  25. this.count++
  26. this.queue.shift()().then(() => {
  27. this.count--
  28. this.request()
  29. })
  30. }
  31. }
  32. // 测试
  33. const scheduler = new Scheduler(2);
  34. const addTask = (time, order) => {
  35. scheduler.add(time, order);
  36. };
  37. addTask(1000, "1");
  38. addTask(500, "2");
  39. addTask(300, "3");
  40. addTask(400, "4");
  41. scheduler.taskStart();

```