behaviors.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import { error, doneInvoke } from './actions.js';
  2. import { toActorRef } from './Actor.js';
  3. import { toObserver } from './utils.js';
  4. /**
  5. * Returns an actor behavior from a reducer and its initial state.
  6. *
  7. * @param transition The pure reducer that returns the next state given the current state and event.
  8. * @param initialState The initial state of the reducer.
  9. * @returns An actor behavior
  10. */
  11. function fromReducer(transition, initialState) {
  12. return {
  13. transition: transition,
  14. initialState: initialState
  15. };
  16. }
  17. function fromPromise(promiseFn) {
  18. var initialState = {
  19. error: undefined,
  20. data: undefined,
  21. status: 'pending'
  22. };
  23. return {
  24. transition: function (state, event, _a) {
  25. var parent = _a.parent,
  26. id = _a.id,
  27. observers = _a.observers;
  28. switch (event.type) {
  29. case 'fulfill':
  30. parent === null || parent === void 0 ? void 0 : parent.send(doneInvoke(id, event.data));
  31. return {
  32. error: undefined,
  33. data: event.data,
  34. status: 'fulfilled'
  35. };
  36. case 'reject':
  37. parent === null || parent === void 0 ? void 0 : parent.send(error(id, event.error));
  38. observers.forEach(function (observer) {
  39. observer.error(event.error);
  40. });
  41. return {
  42. error: event.error,
  43. data: undefined,
  44. status: 'rejected'
  45. };
  46. default:
  47. return state;
  48. }
  49. },
  50. initialState: initialState,
  51. start: function (_a) {
  52. var self = _a.self;
  53. promiseFn().then(function (data) {
  54. self.send({
  55. type: 'fulfill',
  56. data: data
  57. });
  58. }, function (reason) {
  59. self.send({
  60. type: 'reject',
  61. error: reason
  62. });
  63. });
  64. return initialState;
  65. }
  66. };
  67. }
  68. function spawnBehavior(behavior, options) {
  69. if (options === void 0) {
  70. options = {};
  71. }
  72. var state = behavior.initialState;
  73. var observers = new Set();
  74. var mailbox = [];
  75. var flushing = false;
  76. var flush = function () {
  77. if (flushing) {
  78. return;
  79. }
  80. flushing = true;
  81. while (mailbox.length > 0) {
  82. var event_1 = mailbox.shift();
  83. state = behavior.transition(state, event_1, actorCtx);
  84. observers.forEach(function (observer) {
  85. return observer.next(state);
  86. });
  87. }
  88. flushing = false;
  89. };
  90. var actor = toActorRef({
  91. id: options.id,
  92. send: function (event) {
  93. mailbox.push(event);
  94. flush();
  95. },
  96. getSnapshot: function () {
  97. return state;
  98. },
  99. subscribe: function (next, handleError, complete) {
  100. var observer = toObserver(next, handleError, complete);
  101. observers.add(observer);
  102. observer.next(state);
  103. return {
  104. unsubscribe: function () {
  105. observers.delete(observer);
  106. }
  107. };
  108. }
  109. });
  110. var actorCtx = {
  111. parent: options.parent,
  112. self: actor,
  113. id: options.id || 'anonymous',
  114. observers: observers
  115. };
  116. state = behavior.start ? behavior.start(actorCtx) : state;
  117. return actor;
  118. }
  119. export { fromPromise, fromReducer, spawnBehavior };