I currently have this code:
package sage.sys;
import com.dongxiguo.continuation.Async;
#if flash
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.URLLoaderDataFormat;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.SecurityErrorEvent;
#end
class FileSystem implements Async
{
public static function fetchText(url:String, callback:String->Void) : Void
{
var urlLoader = new URLLoader();
var onLoaderError = function(e : Event) : Void {
callback(e.type);
};
urlLoader.addEventListener(Event.COMPLETE, function(_) : Void {
callback(Std.string(urlLoader.data));
});
urlLoader.addEventListener(IOErrorEvent.IO_ERROR, onLoaderError);
urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onLoaderError);
try {
urlLoader.dataFormat = URLLoaderDataFormat.TEXT;
urlLoader.load(new URLRequest(url));
}
catch (e : Dynamic)
{
callback(Std.string(e));
}
}
#async
public static function fetch(url:String):String
{
var result = #await fetchText(url);
return result;
}
}
When I try to run it, it doesn't wait at the await, and returns from the function. How can I make the #await actually enforce itself and and stop running outside the function till the value is resolved from the async call?
Lib used: https://github.com/proletariatgames/haxe-continuation
You can't really. The function, in which you call fetchText() will never "wait" in that sense.
However according to the documentation of "haxe-continuation" it will put everything after your #await FileSystem.fetchText() expression into a new function, which will be passed as the callback parameter of fetchText(). So in code it kind of "looks" like it is waiting.
According to the documentation you have to make sure that you put #async in front of the function which uses fetchText(). According to that something like this should work (untested):
#async function someFunction(): Void {
var result1 = #await FileSystem.fetchText(someUrl);
var result2 = #await FileSystem.fetchText(anotherUrl);
trace(result1);
trace(result2);
}
The 2 traces at the end of the function should happen after result1 and result2 are fetched, even though someFunction() actually returned before the traces already.
It might be helpful to see your code which calls fetchText().
How did you use the fetch function?
I suppose you should put a callback to it:
FileSystem.fetch(url, function(result) trace(result));
The fetch call itself should return immediately, because it is async and the result will be passed to the callback.
I don't think it is possible to make flash block at the fetch call.
Related
I'm looking for a way in sinon to call different functions in first and second call to the stub method.
Here is an example:
var func1 = function(connectionPolicy, requestOptions, callback) {
callback({code: 403});
}
var func2 = function(connectionPolicy, requestOptions, callback) {
callback(undefined);
}
var stub = sinon.stub();
// Something of this form
stub.onCall(0) = func1;
stub.onCall(1) = func2;
request.createRequestObjectStub = stub;
So that when request.createrequestObjectStub gets called internally(when calling a public API), I see this behavior.
Sinon version: 1.17.4
Environment: Node JS
The only way I found to do what you want (with onCall(index) and an anonymous stub) is with bind JS Function.
This would be:
stub.onCall(0).returns(func1.bind()());
stub.onCall(1).returns(func2.bind()());
If you use stub.onCall(0).returns(func1()); the function func1 is executed when defining that onCall, that is why you need the .bind.
Anyway, you have other options, like returning a value directly with .onCall(index).returns(anObject); or defining a counter that is incremented each time your stubbed method is called (this way you know in which n-call you are and you can return different values).
For these three approaches, you can see the following fiddle with examples: https://jsfiddle.net/elbecita/jhvvv1h1/
onCall worked for me.
my code looks like:
const stubFnc = sinon.stub(myObject, "myFunction");
stubFnc.onCall(0).returns(mockObject1);
stubFnc.onCall(1).returns(mockObject2);
This is an old thread, but atleast as of Sinon 1.8, a more efficient way to solve this would be chaining sinon.onCall(arg) with callsFake().
So, in your use-case, you could do the following:
var func1 = function(connectionPolicy, requestOptions, callback) {
callback({code: 403});
}
var func2 = function(connectionPolicy, requestOptions, callback) {
callback(undefined);
}
var stub = sinon.stub();
// Solution
stub.onCall(0).callsFake(func1);
stub.onCall(1).callsFake(func2);
request.createRequestObjectStub = stub;
You can use callsArg and callsArgWith from sinon.stub() to make sinon call the callbacks
Causes the stub to call the argument at the provided index as a callback function. stub.callsArg(0); causes the stub to call the first argument as a callback. source
Then you can do something like:
myStub.onCall(0).callsArgWith(0, first);
myStub.onCall(1).callsArgWith(0, second);
is it possible to create your own futures in Dart to return from your methods, or must you always return a built in future return from one of the dart async libraries methods?
I want to define a function which always returns a Future<List<Base>> whether its actually doing an async call (file read/ajax/etc) or just getting a local variable, as below:
List<Base> aListOfItems = ...;
Future<List<Base>> GetItemList(){
return new Future(aListOfItems);
}
If you need to create a future, you can use a Completer. See Completer class in the docs. Here is an example:
Future<List<Base>> GetItemList(){
var completer = new Completer<List<Base>>();
// At some time you need to complete the future:
completer.complete(new List<Base>());
return completer.future;
}
But most of the time you don't need to create a future with a completer. Like in this case:
Future<List<Base>> GetItemList(){
var completer = new Completer();
aFuture.then((a) {
// At some time you need to complete the future:
completer.complete(a);
});
return completer.future;
}
The code can become very complicated using completers. You can simply use the following instead, because then() returns a Future, too:
Future<List<Base>> GetItemList(){
return aFuture.then((a) {
// Do something..
});
}
Or an example for file io:
Future<List<String>> readCommaSeperatedList(file){
return file.readAsString().then((text) => text.split(','));
}
See this blog post for more tips.
You can simply use the Future<T>value factory constructor:
return Future<String>.value('Back to the future!');
Returning a future from your own function
This answer is a summary of the many ways you can do it.
Starting point
Your method could be anything but for the sake of these examples, let's say your method is the following:
int cubed(int a) {
return a * a * a;
}
Currently you can use your method like so:
int myCubedInt = cubed(3); // 27
However, you want your method to return a Future like this:
Future<int> myFutureCubedInt = cubed(3);
Or to be able to use it more practically like this:
int myCubedInt = await cubed(3);
The following solutions all show ways to do that.
Solution 1: Future() constructor
The most basic solution is to use the generative constructor of Future.
Future<int> cubed(int a) {
return Future(() => a * a * a);
}
I changed the return type of the method to Future<int> and then passed in the work of the old function as an anonymous function to the Future constructor.
Solution 2: Future named constructor
Futures can complete with either a value or an error. Thus if you want to specify either of these options explicitly you can use the Future.value or Future.error named constructors.
Future<int> cubed(int a) {
if (a < 0) {
return Future.error(ArgumentError("'a' must be positive."));
}
return Future.value(a * a * a);
}
Not allowing a negative value for a is a contrived example to show the use of the Future.error constructor. If there is nothing that would produce an error then you can simply use the Future.value constructor like so:
Future<int> cubed(int a) {
return Future.value(a * a * a);
}
Solution 3: async method
An async method automatically returns a Future so you can just mark the method async and change the return type like so:
Future<int> cubed(int a) async {
return a * a * a;
}
Normally you use async in combination with await, but there is nothing that says you must do that. Dart automatically converts the return value to a Future.
In the case that you are using another API that returns a Future within the body of your function, you can use await like so:
Future<int> cubed(int a) async {
return await cubedOnRemoteServer(a);
}
Or this is the same thing using the Future.then syntax:
Future<int> cubed(int a) async {
return cubedOnRemoteServer(a).then((result) => result);
}
Solution 4: Completer
Using a Completer is the most low level solution. You only need to do this if you have some complex logic that the solutions above won't cover.
import 'dart:async';
Future<int> cubed(int a) async {
final completer = Completer();
if (a < 0) {
completer.completeError(ArgumentError("'a' must be positive."));
} else {
completer.complete(a * a * a);
}
return completer.future;
}
This example is similar to the named constructor solution above. It handles errors in addition completing the future in the normal way.
A note about blocking the UI
There is nothing about using a future that guarantees you won't block the UI (that is, the main isolate). Returning a future from your function simply tells Dart to schedule the task at the end of the event queue. If that task is intensive, it will still block the UI when the event loop schedules it to run.
If you have an intensive task that you want to run on another isolate, then you must spawn a new isolate to run it on. When the task completes on the other isolate, it will return a message as a future, which you can pass on as the result of your function.
Many of the standard Dart IO classes (like File or HttpClient) have methods that delegate the work to the system and thus don't do their intensive work on your UI thread. So the futures that these methods return are safe from blocking your UI.
See also
Asynchrony support documentation
Flutter Future vs Completer
#Fox32 has the correct answer addition to that we need to mention Type of the Completer otherwise we get exception
Exception received is type 'Future<dynamic>' is not a subtype of type 'FutureOr<List<Base>>
so initialisation of completer would become
var completer= new Completer<List<Base>>();
Not exactly the answer for the given question, but sometimes we might want to await a closure:
flagImage ??= await () async {
...
final image = (await codec.getNextFrame()).image;
return image;
}();
I think it does create a future implicitly, even though we don't pass it anywhere.
Here a simple conditional Future example.
String? _data;
Future<String> load() async {
// use preloaded data
if (_data != null) return Future<String>.value(_data);
// load data only once
String data = await rootBundle.loadString('path_to_file');
_data = data;
return data;
}
I am deserializing a list of objects from an XML file, and would like to bind to the actual content of those objects in my View, passing over a ViewModel. The problem is that file operations are async and this bubbles all the way up to the ViewModel, where Property getters cannot be marked as such...
Problem
I deserialize all XML files in a folder to Profile objects and store them in a List<Profile>. This method (has to be) marked async.
public static async Task<List<Profile>> GetAllProfiles()
{
DataContractSerializer ser = new DataContractSerializer(typeof(Profile));
StorageFolder folder = await ApplicationData.Current.RoamingFolder.CreateFolderAsync("Profiles", CreationCollisionOption.OpenIfExists);
List<Profile> profiles = new List<Profile>();
foreach (var f in await folder.GetFilesAsync())
{
var fs = await f.OpenStreamForReadAsync();
profiles.Add((Profile)ser.ReadObject(fs));
fs.Dispose();
}
return profiles;
}
Ideal solution 1
The binding property in my ViewModel would then ideally call that static method like this
public async Task<ObservableCollection<string>> Lists
{
get
{
return new ObservableCollection<string>(GetAllProfiles().Select(p => p.Name));
}
}
BUT Properties cannot be marked async
Ideal solution 2
public ObservableCollection<string> Lists
{
get
{
return new ObservableCollection<string>((GetAllProfiles().Result).Select(p => p.Name));
}
}
BUT this never executes (it blocks in the await folder.GetFilesAsync() call for some reason)
Current solution
Calls an async Initialize() method that loads the result of the GetProfiles() function in a variable, and then makes a NotifyPropertyChanged("Lists") call:
public ViewModel()
{
Initialize();
}
public async void Initialize()
{
_profiles = await Profile.GetAllProfiles();
NotifyPropertyChanged("Lists");
}
private List<Profile> _profiles;
public ObservableCollection<string> Lists
{
get
{
if (_profiles != null)
return new ObservableCollection<string>(_profiles.Select(p => p.Name));
else
return null;
}
}
Question
Is there a better way?
Is there a pattern/method that I haven't yet discovered?
Edit
The root of the problem appears when doing non-UI code, and you cannot rely on the NotifyPropertyChanged to do some thread-synchronization stuff. -- The method Initialize has to be awaited and ctors cannot be async, so essentialy this is pattern is useless.
public MyClass()
{
Initialize();
}
public async void Initialize()
{
_profiles = await Profile.GetAllProfiles();
}
private ObservableCollection<Profile> _profiles;
public ObservableCollection<string> Lists
{
get
{
return _profiles; // this will always be null
}
}
Properties can't be async so this solution will not work as you mentioned. Task.Result waits for the task to complete, but this is blocking your UI thread where the I/O operation's async callback returns, so you are deadlocking your application, since the callback is never called. Your solution really is the best way. It could be improved though.
You should make the _profiles field an ObservableCollection, so you would not need to convert the List to the OC every time the list is accessed.
Since you are performing an I/O operation that can take arbitrary amount of time - you should enable some sort of a progress indicator while it is in progress.
In some cases you might want the Lists property to be lazier and only call the Init method the first time it is accessed.
I have a function in Flex which has three function in it.
public function update():void
{
A(); \\Dispatches a event with Remote Call
B(); \\Dispatches another event with Remote Call
C();
}
I wan't to call C() after both A() and B() have returned from their call and set particular variables. How can i do that?
If you find yourself doing this often (esp. with more than 2 remote calls), you might want to write your own custom class that handles AsyncTokens from remote calls with a final result() function that is invoked when all remote calls end in success.
If not, since ActionScript is single-threaded, you can just use a local variable to track whether both calls have succeeded.
private var resultFromRemoteCallA:Object;
private var resultFromRemoteCallB:Object;
private function handleRemoteCallA(event:ResultEvent):void {
resultFromRemoteCallA = event.result;
C();
}
private function handleRemoteCallB(event:ResultEvent):void {
resultFromRemoteCallB = event.result;
C();
}
private function C():void {
if (resultFromRemoteCallA && resultFromRemoteCallB) {
// do some thing with the results.
}
}
private function update():void {
resultFromRemoteCallA = resultFromRemoteCallB = null;
A(); B();
}
If you expect null values, you might want to use a boolean variable to track the invocation of the result handler instead.
EDIT: since the author indicated that the dispatch happens in another class, another way to do it would be to pass along a responder and attach it to the AsyncToken like so (in the callee):
private function dispatchRemoteCall(resultHandler:Function, faultHandler: Function): void {
var resultToken: AsyncToken = remoteObject.foo('bar'); // remoteObject may or may not have a result/fault handler
resultToken.addResponder(new mx.rpc.Responder(resultHandler, faultHandler));
}
Then, you can pass along listeners to be invoked when the remote call finishes (at which point you can choose to let the dispatching class store the result or handle it in the caller), like so:
private function update(): void {
classA.dispatchRemoteCall(handleRemoteCallA, handleRemoteCallAFault);
}
If you find yourself doing this a lot, you may also want to look into having a framework do global event routing, like Parsley or Spring Actionscript.
We've been using Flex for about 6 months here at work, and I found that my first batches of FlexUnit tests involving custom components would tend to follow this sort of pattern:
import mx.core.Application;
import mx.events.FlexEvent;
import flexunit.framework.TestCase;
public class CustomComponentTest extends TestCase {
private var component:CustomComponent;
public function testSomeAspect() : void {
component = new CustomComponent();
// set some properties...
component.addEventListener(FlexEvent.CREATION_COMPLETE,
addAsync(verifySomeAspect, 5000));
component.height = 0;
component.width = 0;
Application.application.addChild(component);
}
public function verifySomeAspect(event:FlexEvent) : void {
// Assert some things about component...
}
override public function tearDown() : void {
try {
if (component) {
Application.application.removeChild(component);
component = null;
}
} catch (e:Error) {
// ok to ignore
}
}
Basically, you need to make sure the component has been fully initialized before you can reliably verify anything about it, and in Flex this happens asynchronously after it has been added to the display list. So you need to setup a callback (using FlexUnit's addAsync function) to be notified when that's happened.
Lately i've been just manually calling the methods that the runtime would call for you in the necessary places, so now my tests tend to look more like this:
import flexunit.framework.TestCase;
public class CustomComponentTest extends TestCase {
public function testSomeAspect() : void {
var component:CustomComponent = new CustomComponent();
component.initialize();
// set some properties...
component.validateProperties();
// Assert some things about component...
}
This is much easier to follow, but it kinda feels like I'm cheating a little either way. The first case is slamming it into the current Application (which would be the unit test runner shell app), and the latter isn't a "real" environment.
I was wondering how other people would handle this sort of situation?
I see nothing wrong with using the async version. I can agree that the second version is shorter, but I'm not sure that I think it's easier to follow. The test does a lot of things that you wouldn't normally do, whereas the first example is more true to how you would use the component outside the test environment.
Also, in the second form you have to make sure that you do exactly what the framework would do, miss one step and your test isn't relevant, and each test must repeat this code. Seems to me it's better to test it in a situation that is as close to the real thing as possible.
You could have a look at dpUint's sequences, they made component testing a little more declarative:
public function testLogin():void {
var passThroughData:Object = new Object();
passThroughData.username = "myuser1";
passThroughData.password = "somepsswd";
var sequence:SequenceRunner = new SequenceRunner(this);
sequence.addStep(new SequenceSetter(form.usernameTI, {text:passThroughData.username}));
sequence.addStep(new SequenceWaiter(form.usernameTI, FlexEvent.VALUE_COMMIT, 100));
sequence.addStep(new SequenceSetter(form.passwordTI, {text:passThroughData.password}));
sequence.addStep(new SequenceWaiter(form.passwordTI, FlexEvent.VALUE_COMMIT, 100));
sequence.addStep(new SequenceEventDispatcher(form.loginBtn, new MouseEvent("click", true, false)));
sequence.addStep(new SequenceWaiter(form, "loginRequested", 100));
sequence.addAssertHandler(handleLoginEvent, passThroughData);
sequence.run();
}
(example from the dpUint wiki, see here for more info).