Get a promise with angular2 in dart from an http request? - dart

It seems in the 2.0.0-beta.12 build they removed angular2.http from dart in favor of using dart's built in http classes.
However if you were to do something like the following then property is null until the request sets the property.
class Component {
var property;
Component() {
HttpRequest.getString("/path/to/something")
.then((resp) {
property = JSON.decode(resp);
});
}
}
What we really want is a promise place holder for the property until the promise is resolved and the view is updated. So how do you do it in angular2 with dart?
Or is there a different dart/angular2 idiomatic way to do it?

HttpRequest.getString(...) returns a Future (Promise in JS/TS land) otherwise you wouldn't be able to call .then(...) on the result.
You can either use async / await
class Component {
var property;
Component() async {
await HttpRequest.getString("/path/to/something")
.then((resp) {
property = JSON.decode(resp);
});
doSomethingAfterRequestReturned();
}
}
nope - you can't use async / await in a constructor.
Alternatives are static methods or an extra call after object creation. Doing extensive work in the constructor is bad practice anyway.
class Component {
Future<Component> createNewInstance() async {
var c = new Component();
await HttpRequest.getString("/path/to/something")
.then((resp) {
c.property = JSON.decode(resp);
});
return c;
}
var property;
}
and use it like
Component.createNewInstance().then((c) => print(c.property));
with an extra call
class Component {
getData() {
return HttpRequest.getString("/path/to/something")
.then((resp) {
property = JSON.decode(resp);
});
}
var property;
}
and use it like
var c = new Component()
c.getData().then((_) => print(c.property));

Related

Why is there no spy functionality in Mockito Dart?

The following code is a simplified example from my code. I have class A which is dependent on class B. I want to test class A, so I mock class B. Then I'm writing a test for a method of class A and inside of that test I write a stub for whenever a method from my mocked class B is called:
fetchData() async {
try {
await b.getData();
} on DioError catch (e) {
switch (e.response!.statusCode) {
case 401:
logout();
throw UnauthorizedException();
default:
throw UnspecifiedDioException(error: e);
}
}
Test written for fetchData() method:
test('check if fetchData calls logout when 401 is returned', () {
when(mockB.getData())
.thenAnswer((_) async =>
throw DioError(
requestOptions: RequestOptions(path: ""),
response: Response(requestOptions: RequestOptions(path: ""), statusCode: 401)));
verify(a.logout()); // doesn't work because A isn't mocked
});
I've read that you can do this very easily with spies but to my surprise spies are available for every language which uses mockito except for dart. It's apparently deprecated but then again how can something be deprecated if there isn't even a newer version to replace it with.
I'd really appreciate it if someone could tell me if there is a convenient workaround for what I'm trying to achieve. Thanks in advance.
Edit: I've changed the question because the former one wasn't making much sense. I just wanna know if there is something like spies in dart or not.
Using mocktail..
You should stub your logout invocation's dependency as well.
class A {
A({required this.api, required this.auth});
// to be mocked
final Api api;
final Auth auth;
Future<void> fetchData() async {
try {
await api.getData();
} catch (e) {
auth.logout();
}
}
}
class Auth {
Future<void> logout() => Future(() {});
}
class Api {
Future<void> getData() => Future(() {});
}
And your test
class MockApi extends Mock implements Api {}
class MockAuth extends Mock implements Auth {}
void main() {
// create mock objects
final mockApi = MockApi();
final mockAuth = MockAuth();
test('when [Api.getData] throws, [Auth.logout] is called', () async {
// create an instance of "A" and use your mock objects
final a = A(api: mockApi, auth: mockAuth);
// use "thenThrow" to throw
when(() => mockApi.getData()).thenThrow('anything');
// use "thenAnswer" for future-returning methods
when(() => mockAuth.logout()).thenAnswer((_) => Future.value(null));
// call the method to "start" the test
await a.fetchData();
// verify logout was called
verify(mockAuth.logout).called(1); // passes
});
}

Provide function context in dart

So i need to run some code that needs to get some data later.
I imagine it like:
voin runWithContext(void Function () fn, dynamic context) {
// ... magic
fn();
}
And later in the call stack of fn()
void otherFn() {
dynamic context = getContext();
}
If functions are not async we could just store the context as global variable, but the main requirement to support dart:async
I was looking into dart:mirrors and stacktrace but i can't find no way to bind some data.
You can do this with Zones.
Zones, and their "zone variables" are the canonical way to create a context that is preserved throughout an asynchronous computation).
Since you want single global function to access the context, it will have to be untyped (or typed at the one type that you need, but not generally reusable). That would me me want to reconsider the design, but if it works for you, I'd do it as:
import "dart:async";
/// Container for a mutable value.
class _Context {
dynamic value;
}
final _Context _rootContext = _Context();
R runWithNewContext<R>(R Function() body) =>
runZoned(body, zoneValues: {
#_context: _Context()..value = context,
});
dynamic get context => (Zone.current[#_context] ?? _rootContext).value;
set context(dynamic value) {
(Zone.current[#_context] ?? _rootContext).value = value;
}
If you don't need the mutability, you can simplify things a little, but not much.
The typed and unmodifable alternative is something like
class _Box { // Distinguishable from `null`, even if value is `null`
final Object? value;
_Box(this.value);
}
class ZoneStorage<T> {
final _Box _initialValue;
ZoneStorage(T initialValue) : _initialValue = _Box(initialValue);
R update<R>(T newValue, R Function() body) =>
runZoned(body, zoneValues: {this: _Box(newValue)});
T get value =>
(Zone.current[this] as _Box? ?? _initialValue).value as T;
}
That allows you to create multiple independent zone stores, like:
var zs1 = ZoneStorage<int>(1);
var zs2 = ZoneStorage<String>("yup");
zs1.update(42, () {
print(zs1.value);
print(zs2.value);
});
zs2.update("yup yup yup", () {
print(zs1.value);
print(zs2.value);
});
So the thing that is need is https://api.dart.dev/stable/2.17.3/dart-async/Zone-class.html
Hope that answer will help someone else

Create a Future from an other Future "value" in Dart

I have some difficulty to wrap a function that returns a Future.
I have the following code :
class Foo {
Bar data;
}
Future<Foo> getFutureFoo() {...}
I'm would like to create a wrapper that directly returns a Future<Bar>
Future<Bar> getFutureFooBar() {
var foo_future = getFutureFoo();
???
return bar_future;
}
Is there some kind of future transformer like for Streams ?
Future<Bar> getFutureFooBar() async {
Foo foo_future = await getFutureFoo();
//use the foo object to create the Bar object
return bar_future;
}

Interception Using StructureMap 3.*

I've done interception using Castle.DynamicProxy and StructureMap 2.6 API but now can't do it using StructureMap 3.0. Could anyone help me find updated documentation or even demo? Everything that I've found seems to be about old versions. e.g. StructureMap.Interceptors.TypeInterceptor interface etc.
HAHAA! I f***in did it! Here's how:
public class ServiceSingletonConvention : DefaultConventionScanner
{
public override void Process(Type type, Registry registry)
{
base.Process(type, registry);
if (type.IsInterface || !type.Name.ToLower().EndsWith("service")) return;
var pluginType = FindPluginType(type);
var delegateType = typeof(Func<,>).MakeGenericType(pluginType, pluginType);
// Create FuncInterceptor class with generic argument +
var d1 = typeof(FuncInterceptor<>);
Type[] typeArgs = { pluginType };
var interceptorType = d1.MakeGenericType(typeArgs);
// -
// Create lambda expression for passing it to the FuncInterceptor constructor +
var arg = Expression.Parameter(pluginType, "x");
var method = GetType().GetMethod("GetProxy").MakeGenericMethod(pluginType);
// Crate method calling expression
var methodCall = Expression.Call(method, arg);
// Create the lambda expression
var lambda = Expression.Lambda(delegateType, methodCall, arg);
// -
// Create instance of the FuncInterceptor
var interceptor = Activator.CreateInstance(interceptorType, lambda, "");
registry.For(pluginType).Singleton().Use(type).InterceptWith(interceptor as IInterceptor);
}
public static T GetProxy<T>(object service)
{
var proxyGeneration = new ProxyGenerator();
var result = proxyGeneration.CreateInterfaceProxyWithTarget(
typeof(T),
service,
(Castle.DynamicProxy.IInterceptor)(new MyInterceptor())
);
return (T)result;
}
}
The problem here was that SM 3.* allows interception for known types, i.e. doing something like this:
expression.For<IService>().Use<Service>().InterceptWith(new FuncInterceptor<IService>(service => GetProxyFrom(service)));
But what if you'd like to include the interception logic inside your custom scanning convention where you want to intercept all instances of type with specific signature (types having name ending on 'service', in my case)?
That's what I've accomplished using Expression API and reflection.
Also, I'm using here Castle.DinamicProxy for creating proxy objects for my services.
Hope someone else will find this helpful :)
I find the best place to go for any new versions is directly to the source.
If it's written well, then it will include test cases. Thankfully structuremap does include test cases.
You can explore the tests here
In the meantime I've written an example of an Activator Interceptor, and how to configure it.
static void Main()
{
ObjectFactory.Configure(x =>
{
x.For<Form>().Use<Form1>()
.InterceptWith(new ActivatorInterceptor<Form1>(y => Form1Interceptor(y), "Test"));
});
Application.Run(ObjectFactory.GetInstance<Form>());
}
public static void Form1Interceptor(Form f)
{
//Sets the title of the form window to "Testing"
f.Text = "Testing";
}
EDIT:
How to use a "global" filter using PoliciesExpression
[STAThread]
static void Main()
{
ObjectFactory.Configure(x =>
{
x.Policies.Interceptors(new InterceptorPolicy<Form>(new FuncInterceptor<Form>(y => Intercept(y))));
});
Application.Run(ObjectFactory.GetInstance<Form>());
}
private static Form Intercept(Form form)
{
//Do the interception here
form.Text = "Testing";
return form;
}

Loading classes dynamically in Dart

So, I looked into mirror and they might be an option, but given their async nature they might be really awkward to use or just not viable in the long run. Since they are currently not supported (just a play-thing) they are not really viable at this time anyway.
Question: Given a series of Strings, eg. [ "Foo", "Bar" ] a base class Application and Widget in library corelib; and a corresponding class for each of the strings FooWidget, BarWidget in library applibrary;, what's currently the most elegant method to get Application to turn the strings into instances of the corresponding classes, that works with dart2js.
Equivalent PHP pseudo-example for clarity,
<?php # example
namespace corelib;
class Widget {
function name() {
return \get_called_class();
}
}
class Application {
static function resolve($name, $library) {
$class = $library.'\\'.$name.'Widget';
return new $class;
}
}
namespace applibrary;
class FooWidget extends \corelib\Widget {
// ...
}
class BarWidget extends \corelib\Widget {
// ...
}
$foowidget = \corelib\Application::resolve('Foo', 'applibrary');
$barwidget = \corelib\Application::resolve('Bar', 'applibrary');
echo "{$foowidget->name()} <br> {$barwidget->name()}";
Output
applibrary\FooWidget
applibrary\BarWidget
If you can validate the list of strings, then the best way for the moment (until mirror support in dart2js becomes better baked), is likely an if statement.
// toy implementation
Widget getWidget(name) {
switch (name) {
case "Foo": return new FooWidget();
case "Bar": return new FooWidget();
default: // handle error
}
}
// elsewhere:
var fooWidget = getWidget("Foo");
var barWidget = getWidget("Bar");
The list of xyzWidget classes will be a finite list (as you can't dynamically link in code at runtime anyway).
Of course, a more elegant implementation is to use mirrors (shown below, for reference, although it doesn't currently fulfil the dar2js criteria)
Future<Widget> getWidget(library, name) {
var completer = new Completer<Widget>();
MirrorSystem ms = currentMirrorSystem();
ClassMirror cm = ms.libraries[library].classes[name];
// instantiate an instance of the class
cm.newInstance(null,[]).then((instance) => completer.complete(instance));
return completer.future;
}
// elsewhere:
getWidget("applibrary","FooWidget").then((Widget widget) {
// do something with widget
});

Resources