asyncGenerator.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. export default (function () {
  2. function AwaitValue(value) {
  3. this.value = value;
  4. }
  5. function AsyncGenerator(gen) {
  6. var front, back;
  7. function send(key, arg) {
  8. return new Promise(function (resolve, reject) {
  9. var request = {
  10. key: key,
  11. arg: arg,
  12. resolve: resolve,
  13. reject: reject,
  14. next: null
  15. };
  16. if (back) {
  17. back = back.next = request;
  18. } else {
  19. front = back = request;
  20. resume(key, arg);
  21. }
  22. });
  23. }
  24. function resume(key, arg) {
  25. try {
  26. var result = gen[key](arg);
  27. var value = result.value;
  28. if (value instanceof AwaitValue) {
  29. Promise.resolve(value.value).then(function (arg) {
  30. resume("next", arg);
  31. }, function (arg) {
  32. resume("throw", arg);
  33. });
  34. } else {
  35. settle(result.done ? "return" : "normal", result.value);
  36. }
  37. } catch (err) {
  38. settle("throw", err);
  39. }
  40. }
  41. function settle(type, value) {
  42. switch (type) {
  43. case "return":
  44. front.resolve({
  45. value: value,
  46. done: true
  47. });
  48. break;
  49. case "throw":
  50. front.reject(value);
  51. break;
  52. default:
  53. front.resolve({
  54. value: value,
  55. done: false
  56. });
  57. break;
  58. }
  59. front = front.next;
  60. if (front) {
  61. resume(front.key, front.arg);
  62. } else {
  63. back = null;
  64. }
  65. }
  66. this._invoke = send;
  67. if (typeof gen.return !== "function") {
  68. this.return = undefined;
  69. }
  70. }
  71. if (typeof Symbol === "function" && Symbol.asyncIterator) {
  72. AsyncGenerator.prototype[Symbol.asyncIterator] = function () {
  73. return this;
  74. };
  75. }
  76. AsyncGenerator.prototype.next = function (arg) {
  77. return this._invoke("next", arg);
  78. };
  79. AsyncGenerator.prototype.throw = function (arg) {
  80. return this._invoke("throw", arg);
  81. };
  82. AsyncGenerator.prototype.return = function (arg) {
  83. return this._invoke("return", arg);
  84. };
  85. return {
  86. wrap: function (fn) {
  87. return function () {
  88. return new AsyncGenerator(fn.apply(this, arguments));
  89. };
  90. },
  91. await: function (value) {
  92. return new AwaitValue(value);
  93. }
  94. };
  95. })();