tag:robotlegs.tenderapp.com,2009-10-18:/discussions/problems/681-response-from-command-with-signalRobotlegs: Discussion 2012-11-20T10:07:17Ztag:robotlegs.tenderapp.com,2009-10-18:Comment/208980762012-11-16T00:33:53Z2012-11-16T00:33:53ZResponse from command with signal<div><p>Hello,<br>
I started to switch from Events to Signals and I have little
architecture problem.</p>
<p>Let's say:<br>
1) I have UrlRequestService, which sends url request to given url
with some arguments<br>
2) I handle it with SendRequestCommand<br>
3) And I call SendRequestCommand command with SendRequestEvent</p>
<p>When I send request, by calling command with event, I'ld like to
get some response. In Event era, I just passed through
SendRequestEvent local type strings for response and error events,
which command caller listened to. When I've got response or error
from called request, I removed listeners from commands caller and
everything seemed to be clean ( command caller didnt have any
listeners after command resolved).</p>
<p>However, when I wanted to change events to signals I've got some
problem.</p>
<p>Let's say I have points 1 and 2 the same and:<br>
3) I call SendRequestCommand command with injected
SendRequestSignal</p>
<p>In this case, I initiate in commands caller temporary signals,
which are sent through SendRequestSignal when I call
SendRequestCommand. After SendRequestCommand resolves, commands
caller response or error signal will be dispatched. The problem
occurs, when I whant to remove listeners from command caller
signals.</p>
<p>I can use signal.addOnce function. However, when response
occurs, response signal will remove its listener, but error signal
will still listen for error, which will never occur. The same in
situtation when error occurs.</p>
<p>I want to avoid the situtation, when I have to assign those
signals as class variables. They should be temporary listeners
which are removed after response or error occurs.</p>
<p>I could send themselves in dispatched response or error, but
that doesnt sound good.</p>
<p>Is there any other solution to my command response problem? Did
I miss some robotlegs native functionality or forget about some
major pattern?</p></div>maciekreitag:robotlegs.tenderapp.com,2009-10-18:Comment/208980762012-11-16T10:20:33Z2012-11-16T10:20:33ZResponse from command with signal<div><p>Hey Maciej,</p>
<p>Let’s see if I understood the use case.</p>
<p>In SomeClass you dispatch SomeEvent.DATA_REQUESTED, that
triggers a command-> service.</p>
<p>SomeClass added 2 listeners:<br>
1. SomeEvent.DATA_RECEIVED and a handler onDataReceived<br>
2. SomeEvent.REQUEST_FAILED and a handler onRequestFailed<br>
3. In onDataReceived() you do something with the data and then
call, say, removeRequestEvents(). In this method you remove both
events, 1 + 2. Same for onRequestFailed, you do something with the
error mesagge (or not), then you call removeRequestEvents().</p>
<p>That’s what you can do with signals, too, remove both
listeners, when one of the 2 signals has been handled.</p>
<p>Of course, that’s possible if both handlers are in the
same class. If one class listens for SomeEvent.DATA_RECEIVED and
another class for REQUEST_FAILED, one of the handlers won’t
be called.</p>
<p>Now, the question is, are you handling both signals within the
same class? If the answer is yes, would my suggestion from above
work for you?</p>
<p>Ondina</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/208980762012-11-16T12:50:06Z2012-11-16T14:11:16ZResponse from command with signal<div><p>Hey Odina,<br>
yes, your assumtions are correct. I do exactly like you listed in
points 1-3 and handlers are in the same class. But how can I remove
listeners from signals? In events I've got targets instance, so
removing it's listeners wasnt a problem. Bt here I need instance of
both signals wich I dont have. E.g.:</p>
<pre>
<code>[Inject]
public var commandCaller:Signal;
private function callCommand():void {
var response:Signal = new Signal(Object);
response.addOnce(onResponse);
var error:Signal = new Signal(String);
error.addOnce(onError);
callCaler.dispatch(response,error);
}
private function onResponse(message:Object):void
//response listener is already removed but what about error listener?
}
private function onError(error:String):void
//error listener is already removed but what about response listener?
}</code>
</pre>
<p>I could send their instance through response/error along with
message/error parameter, but that doesnt seem pretty.</p></div>maciekreitag:robotlegs.tenderapp.com,2009-10-18:Comment/208980762012-11-16T14:45:55Z2012-11-16T14:45:55ZResponse from command with signal<div><p><strong>A Mediator</strong></p>
<pre>
<code> [Inject]
public var sendRequestSignal:SendrequestSignal;
[Inject]
public var signalDataVO:SignalDataVO;
private var response:Signal;
private var error:Signal;
override public function onRegister():void
{
response = new Signal(Object);
response.add(onResponse);
error = new Signal(String);
error.add(onError);
signalDataVO.responseSignal = response;
signalDataVO.errorSignal = error;
sendRequestSignal.dispatch(signalDataVO);
}
private function onResponse(message:String):void
{
trace("onResponse(message) " + message);
removeSignalsListeners();
}
private function onError(error:String):void
{
trace("onError(error) " + error);
removeSignalsListeners();
}
private function removeSignalsListeners():void
{
error.removeAll();
response.removeAll();
trace("error.numListeners " + error.numListeners + " response.numListeners " + response.numListeners);
}</code>
</pre>
<p><strong>VO</strong></p>
<pre>
<code>package yourdomain.models.vo
{
import org.osflash.signals.Signal;
public class SignalDataVO
{
private var _responseSignal:Signal;
private var _errorSignal:Signal;
public function SignalDataVO()
{
}
public function get errorSignal():Signal
{
return _errorSignal;
}
public function set errorSignal(value:Signal):void
{
_errorSignal = value;
}
public function get responseSignal():Signal
{
return _responseSignal;
}
public function set responseSignal(value:Signal):void
{
_responseSignal = value;
}
}
}</code>
</pre>
<p><strong>Signal</strong></p>
<pre>
<code>package yourdomain.controllers.signals
{
import org.osflash.signals.Signal;
import yourdomain.models.vo.SignalDataVO;
public class SendrequestSignal extends Signal
{
public function SendrequestSignal()
{
super(SignalDataVO);
}
}
}</code>
</pre>
<p><strong>Command</strong></p>
<pre>
<code>package yourdomain.controllers.commands
{
import org.robotlegs.mvcs.Command;
import yourdomain.models.vo.SignalDataVO;
public class SendRequestCommand extends Command
{
[Inject]
public var signalDataVO:SignalDataVO;
public function SendRequestCommand()
{
}
override public function execute():void
{
trace("SendRequestCommand.execute() ");
//say, you dispatch one of them:
signalDataVO.responseSignal.dispatch("data");
//signalDataVO.errorSignal.dispatch("error");
}
}
}</code>
</pre>
<p>Would that be a solution for you?</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/208980762012-11-17T11:34:23Z2012-11-17T11:34:23ZResponse from command with signal<div><p>Yes, it is solution for me. Although I was strugling before with
this implementation, because it some times can cause a lot of
response signals. All in all, thank you for your contribution.</p></div>maciekreitag:robotlegs.tenderapp.com,2009-10-18:Comment/208980762012-11-20T10:07:12Z2012-11-20T10:07:12ZResponse from command with signal<div><p>Hi Maciek,</p>
<blockquote>
<p>Yes, it is solution for me. Although I was strugling before with
this implementation, because it some times can cause a lot of
response signals. All in all, thank you for your contribution.</p>
</blockquote>
<p>You’re welcome.<br>
You’ll have to decide what’s best for you, using the
request/response signal pairs, or 2 signals, an ErrorSignal and a
ResponseSignal (with names of your choice), which you’d
inject into your command as well.</p>
<p>Cheers,<br>
Ondina</p></div>Ondina D.F.