lib/flowRuntime.js
/**
 * Resume a flow ... should only be called by middleware or a flow instance managing a subflow ending and the
 * parent continuing. The requested event MUST be set before calling this method.
 *
 * @param flowObj
 * @param context
 * @param alreadyRunning  set to true if you are returning from subflows and resuming parent flow
 */
Resume a flow ... should only be called by middleware or a flow instance managing a subflow ending and the
parent continuing. The requested event MUST be set before calling this method.

@param flowObj
@param context
@param alreadyRunning  set to true if you are returning from subflows and resuming parent flow
Resume a flow ... should only be called by middleware or a flow instance managing a subflow ending and the parent continuing . The requested event MUST be set before calling this method . @param flowObj @param context @param alreadyRunning set to true if you are returning from subflows and resuming parent flow
function resume(flowObj, context, alreadyRunning) {
    assert(context, 'Can not resume a flow without a context.');
    assert(flowObj.currentStateId, 'Can not resume a flow without initializing it.');
    if(!alreadyRunning) {
        flowObj._registerInternalListener('error', flowObj._errorCoordinator);
        flowObj._registerFlowEventListeners();
    }
    var self = flowObj;
    var transition = flowObj.statesByName[flowObj.currentStateName].transitions[flowObj.requestedEvent];
    if(flowObj.isEndState(transition._toState) && !transition._onExit) {
        flowObj._addComprehensiveStateHistory(flowObj.currentStateName);
        flowObj._endStateReached(context, transition._toState);
        if(!flowObj.isSubflow) {
            return flowObj._render(context);
        }
        else {
            return subflowEnded(flowObj._parent, transition._toState, context, flowObj.name);
        }
    }
    else {
        flowObj.setRequestedStateNameAndContext(transition._toState, context);
        if(transition._onExit) {
            if(flowObj.statesByName[flowObj.requestedStateName].type === State.types.SUBFLOW) {
                flowObj._authorize(context, flowObj.statesByName[flowObj.requestedStateName].flowName, function(allowed) {
                    var reallySelf = self;
                    if(!allowed)  {
                        return self._render(context);
                    }
                    else {
                        onExit(self, context, transition._onExit, function(endState, runSubflow, subflow, subflowContext) {
                            if(runSubflow){
                                assert(reallySelf.name !== subflow.name,
                                    'Attempting to run a flow: ' + reallySelf.name + ' back on itself');
                                return run(subflow, subflowContext);
                            }
                            else if(reallySelf.isSubflow && reallySelf.currentStateName === State.states.FLOW_COMPLETE) {
                                return subflowEnded(reallySelf._parent, endState, context, reallySelf.name);
                            }
                            else {
                                return reallySelf._render(context);
                            }
                        });
                    }
                });
            }
            else {
                onExit(flowObj, context, transition._onExit, function(endState, runSubflow, subflow, subflowContext){
                    if(runSubflow) {
                        debug('>>>>>>>>>>>>>>>>>>>>   About to run subflow: ' + subflow.name);
                        assert(self.name !== subflow.name, 'Attempting to run a flow: ' + self.name + ' back on itself');
                        return subflow.run(subflowContext);
                    }
                    else if(self.isSubflow && self.currentStateName === State.states.FLOW_COMPLETE) {
                        return subflowEnded(self._parent, endState, context, self.name);
                    }
                    else {
                        return self._render(context);
                    }
                });
            }
        }
        else {
            if(flowObj.statesByName[flowObj.requestedStateName].type === State.types.SUBFLOW) {
                flowObj._authorize(context, flowObj.statesByName[flowObj.requestedStateName].flowName, function(allowed) {
                    if(allowed)  {
                        self._preRunSubflow(context);
                        return run(self.subflows[self.currentSubflowName], context);
                    }
                    else {
                        return self._render(context);
                    }
                });
            }
            else {
                onEntry(flowObj, context, function(endState, runSubflow, subflow, subflowContext){
                    if(runSubflow) {
                        debug('>>>>>>>>>>>>>>>>>>>>   About to run subflow: ' + subflow.name);
                        assert(self.name !== subflow.name, 'Attempting to run a flow: ' + self.name + ' back on itself');
                        return run(subflow, subflowContext);
                    }
                    else if(self.isSubflow && self.currentStateName === State.states.FLOW_COMPLETE) {
                        return subflowEnded(self._parent, endState, context, self.name);
                    }
                    else {
                        return self._render(context);
                    }
                });
            }
        }
    }
}
function resume ( flowObj , context , alreadyRunning ) { assert ( context , 'Can not resume a flow without a context.' ) ; assert ( flowObj . currentStateId , 'Can not resume a flow without initializing it.' ) ; if ( ! alreadyRunning ) { flowObj . _registerInternalListener ( 'error' , flowObj . _errorCoordinator ) ; flowObj . _registerFlowEventListeners ( ) ; } var self = flowObj ; var transition = flowObj . statesByName [ flowObj . currentStateName ] . transitions [ flowObj . requestedEvent ] ; if ( flowObj . isEndState ( transition . _toState ) && ! transition . _onExit ) { flowObj . _addComprehensiveStateHistory ( flowObj . currentStateName ) ; flowObj . _endStateReached ( context , transition . _toState ) ; if ( ! flowObj . isSubflow ) { return flowObj . _render ( context ) ; } else { return subflowEnded ( flowObj . _parent , transition . _toState , context , flowObj . name ) ; } } else { flowObj . setRequestedStateNameAndContext ( transition . _toState , context ) ; if ( transition . _onExit ) { if ( flowObj . statesByName [ flowObj . requestedStateName ] . type === State . types . SUBFLOW ) { flowObj . _authorize ( context , flowObj . statesByName [ flowObj . requestedStateName ] . flowName , function ( allowed ) { var reallySelf = self ; if ( ! allowed ) { return self . _render ( context ) ; } else { onExit ( self , context , transition . _onExit , function ( endState , runSubflow , subflow , subflowContext ) { if ( runSubflow ) { assert ( reallySelf . name !== subflow . name , 'Attempting to run a flow: ' + reallySelf . name + ' back on itself' ) ; return run ( subflow , subflowContext ) ; } else if ( reallySelf . isSubflow && reallySelf . currentStateName === State . states . FLOW_COMPLETE ) { return subflowEnded ( reallySelf . _parent , endState , context , reallySelf . name ) ; } else { return reallySelf . _render ( context ) ; } } ) ; } } ) ; } else { onExit ( flowObj , context , transition . _onExit , function ( endState , runSubflow , subflow , subflowContext ) { if ( runSubflow ) { debug ( '>>>>>>>>>>>>>>>>>>>>   About to run subflow: ' + subflow . name ) ; assert ( self . name !== subflow . name , 'Attempting to run a flow: ' + self . name + ' back on itself' ) ; return subflow . run ( subflowContext ) ; } else if ( self . isSubflow && self . currentStateName === State . states . FLOW_COMPLETE ) { return subflowEnded ( self . _parent , endState , context , self . name ) ; } else { return self . _render ( context ) ; } } ) ; } } else { if ( flowObj . statesByName [ flowObj . requestedStateName ] . type === State . types . SUBFLOW ) { flowObj . _authorize ( context , flowObj . statesByName [ flowObj . requestedStateName ] . flowName , function ( allowed ) { if ( allowed ) { self . _preRunSubflow ( context ) ; return run ( self . subflows [ self . currentSubflowName ] , context ) ; } else { return self . _render ( context ) ; } } ) ; } else { onEntry ( flowObj , context , function ( endState , runSubflow , subflow , subflowContext ) { if ( runSubflow ) { debug ( '>>>>>>>>>>>>>>>>>>>>   About to run subflow: ' + subflow . name ) ; assert ( self . name !== subflow . name , 'Attempting to run a flow: ' + self . name + ' back on itself' ) ; return run ( subflow , subflowContext ) ; } else if ( self . isSubflow && self . currentStateName === State . states . FLOW_COMPLETE ) { return subflowEnded ( self . _parent , endState , context , self . name ) ; } else { return self . _render ( context ) ; } } ) ; } } } }
Resume a flow ... should only be called by middleware or a flow instance managing a subflow ending and the
 parent continuing.
Resume a flow ... should only be called by middleware or a flow instance managing a subflow ending and the parent continuing .
// do NOT re-register exising listeners // Handle a requestEvent that could be an end state transition // Case: End event and No onExit method to call first // in a VIEW state // if you successful execute onExit for flow VIEW then you will be transitioning to a SUBFLOW // you are in a VIEW state and you next transition is not a SUBFLOW // must call onExit first then call next state which could be: end, view, action, or subflow // you are NOT in a view state with an onExit method // Authorize, set current to requested, copy context for subflow and run subflow // No subflow so run onEntry for either ACTON or VIEW state