11import { Component } from 'react' ;
22import isEqual from 'shallowequal' ;
33
4- export default class Coroutine extends Component {
5- static create ( asyncFn ) {
6- return class AsyncComponent extends Coroutine {
7- static get contextTypes ( ) {
8- return asyncFn . contextTypes ;
9- }
10-
11- static get displayName ( ) {
12- return `Coroutine(${ asyncFn . name } )` ;
13- }
14-
15- observe ( props , context ) {
16- return asyncFn ( props , context ) ;
17- }
4+ export default { create } ;
185
19- render ( ) {
20- return this . state . data ;
21- }
6+ function create ( asyncFn ) {
7+ let displayName = asyncFn . name || asyncFn . displayName || 'Anonymous' ;
8+ return class extends Coroutine {
9+ static get displayName ( ) {
10+ return `Coroutine(${ displayName } )` ;
2211 }
23- }
2412
25- static get displayName ( ) {
26- return `Coroutine(${ this . name } )` ;
13+ observe ( props ) {
14+ return asyncFn ( props ) ;
15+ }
2716 }
17+ }
2818
29- constructor ( props , context ) {
30- super ( props , context ) ;
19+ class Coroutine extends Component {
20+ constructor ( props ) {
21+ super ( props ) ;
3122 this . state = { data : null } ;
3223 this . iterator = null ;
33- this . forceUpdateHelper = this . forceUpdate . bind ( this ) ;
3424 this . isComponentMounted = false ;
3525 }
3626
@@ -50,21 +40,43 @@ export default class Coroutine extends Component {
5040 }
5141 } ) ;
5242 } else {
53- const getNextBody = ( ) => {
54- this . iterator . next ( ) . then ( ( data ) => {
55- if ( ! this . isComponentMounted || this . iterator !== asyncBody ) {
56- return ;
43+ function resolveSyncIterator ( i , step , cb ) {
44+ if ( ! step . done ) {
45+ if ( step . value && typeof step . value . then === 'function' ) {
46+ step . value . then ( data => resolveSyncIterator ( i , i . next ( data ) , cb ) ) ;
47+ } else {
48+ resolveSyncIterator ( i , i . next ( step . value ) , cb ) ;
5749 }
50+ } else {
51+ cb ( step . value ) ;
52+ }
53+ } ;
5854
55+ function resolveAsyncIterator ( i , step , cb ) {
56+ step . then ( ( data ) => {
5957 if ( data . value !== undefined ) {
60- this . setState ( ( ) => ( { data : data . value } ) ) ;
58+ cb ( data . value ) ;
6159 }
6260
63- return ! data . done && getNextBody ( ) ;
61+ return ! data . done && resolveAsyncIterator ( i , i . next ( ) , cb ) ;
6462 } ) ;
6563 } ;
6664
67- getNextBody ( ) ;
65+ function resolveIterator ( iterator , instance ) {
66+ const step = iterator . next ( ) ;
67+
68+ const updater = ( data ) => {
69+ return instance . isComponentMounted && instance . setState ( { data } ) ;
70+ } ;
71+
72+ if ( typeof step . then === 'function' ) {
73+ resolveAsyncIterator ( iterator , step , updater ) ;
74+ } else {
75+ resolveSyncIterator ( iterator , step , updater ) ;
76+ }
77+ } ;
78+
79+ resolveIterator ( this . iterator , this ) ;
6880 }
6981 }
7082
@@ -94,6 +106,6 @@ export default class Coroutine extends Component {
94106 }
95107
96108 render ( ) {
97- throw new Error ( 'Coroutine::render should be implemented by a subclass' ) ;
109+ return this . state . data ;
98110 }
99111}
0 commit comments