When i try to use future.sync from class future like
import 'package:async/async.dart';
import 'dart:async';
void main() {
var fur3 = new Future<int>(() => 45);
int z = Future.sync(fur3);
print(z);
}
i've got the error message
Breaking on exception: object of type NoSuchMethodError
Do i use future.sync in the wrong way?
My second question is
import 'package:async/async.dart';
void main() {
var fur1 = new Future<int>(() => 45);
fur1.then((value) {
return value;
}).catchError((err) => print('catchError1: ${err}'));
}
why when i try to import async library from package, i've got compiler message
Breaking on exception: object of type TypeError
Undefined class 'Future'
what am i do here wrong?
You don't pass a future into Future.sync() but a closure to be executed immediately.
Future z = Future.sync(() => print('bla'));
async is an internal package. You import it using
import 'dart:async';
Internal packages don't need to be added to pubspec.yaml dependencies because they are always available. The different import statement is related to that.
Related
I am trying to upgrade Dart1 application to Dart 2.4, I am facing a problem in Router my code is as shown below
import 'dart:async';
import 'dart:convert';
import 'package:angular/src/core/di/decorators.dart';
#Injectable()
class SpRouterImpl implements SpRouter {
final Router _router;
SpRouterImpl(this._router);
#override
void go(String routeName, Map<String, String> parameters,
[bool openInNewWindow = false]) {
if (openInNewWindow) {
var url = _router.generate([routeName, parameters]).component.urlPath;
window.open(url, "_blank");
} else {
_router.navigate([routeName, parameters]);
}
}
}
I am getting error in this line
var url = _router.generate([routeName, parameters]).component.urlPath;
The method generate isn't defined for the class Router
Second error is here
_router.navigate([routeName, parameters]);
The argument type List can't be assigned to the parameter type 'String'
The above function is working fine in Dart 1 but when I upgrade to Dart 2, I am getting the errors, don't know how to solve it.
Can anyone help in this regard
You need a RoutePath instance to define your "route".
final search = RoutePath(path: "search/:term"); // term is the parameter
Then use that path to navigate to that route.
_router.navigate(search.toUrl(parameters: {'term': searchTerm}));
So in your case it might look like this:
import 'dart:async';
import 'dart:convert';
import 'package:angular/src/core/di/decorators.dart';
#Injectable()
class SpRouterImpl implements SpRouter {
final Router _router;
SpRouterImpl(this._router);
#override
void go(String routeName, Map<String, String> parameters,
[bool openInNewWindow = false]) {
final path = RoutePath(routeName);
final url = path.toUrl(parameters: parameters)
if (openInNewWindow) {
window.open(url, "_blank");
} else {
_router.navigate(url);
}
}
}
It might not drop in and work depending on how your routeName is defined but this is the general idea.
There are several other options for RoutePath check them out and see what works best for you!
I'm trying to figure out how to specify types in code like this:
import 'dart:convert';
import 'package:http/http.dart' as http;
main() async {
Map repos = await(fetchJson());
print(repos['name']);
}
Object fetchJson() async {
final uri = 'https://api.github.com/users/sjindel-google/repos';
final response = await http.get(uri);
return jsonDecode(response.body)[1];
}
That code works, but I want to specify the type for fetchJson(). It seems like it should be:
Future<Map> fetchJson() async {
But that gives me the runtime error:
Error: 'Future' expects 0 type arguments.
What's the right way to do this?
Trying to use Mockito to test my BLoC, the BLoC makes a server call using a repository class and the server call function is supposed to throw a custom exception if the user is not authenticated.
But when I am trying to stub the repository function to throw that custom exception, the test just fails with the following error:
sunapsis Authorization error (test error): test description
package:mockito/src/mock.dart 342:7 PostExpectation.thenThrow.<fn>
package:mockito/src/mock.dart 119:37 Mock.noSuchMethod
package:sunapsis/datasource/models/notifications_repository.dart 28:37 MockNotificationRepository.getNotificationList
package:sunapsis/blocs/notification_blocs/notification_bloc.dart 36:10 NotificationBloc.fetchNotifications
test/blocs/notification_blocs/notification_bloc_test.dart 53:48 main.<fn>.<fn>.<fn>
===== asynchronous gap ===========================
dart:async scheduleMicrotask
test/blocs/notification_blocs/notification_bloc_test.dart 53:7 main.<fn>.<fn>
And this is what my BLoC code looks like: fetchNotifications function calls the repository function and handles the response and errors. There are two catchError blocks, one handles AuthorizationException case and other handles any other Exception. Handling AuthorizationException differently because it will be used to set the Login state of the application.
notification_bloc.dart
import 'dart:async';
import 'package:logging/logging.dart';
import 'package:rxdart/rxdart.dart';
import 'package:sunapsis/datasource/dataobjects/notification.dart';
import 'package:sunapsis/datasource/models/notifications_repository.dart';
import 'package:sunapsis/utils/authorization_exception.dart';
class NotificationBloc {
final NotificationsRepository _notificationsRepository;
final Logger log = Logger('NotificationBloc');
final _listNotifications = PublishSubject<List<NotificationElement>>();
final _isEmptyList = PublishSubject<bool>();
final _isLoggedIn = PublishSubject<bool>();
Observable<List<NotificationElement>> get getNotificationList =>
_listNotifications.stream;
Observable<bool> get isLoggedIn => _isLoggedIn.stream;
Observable<bool> get isEmptyList => _isEmptyList.stream;
NotificationBloc({NotificationsRepository notificationsRepository})
: _notificationsRepository =
notificationsRepository ?? NotificationsRepository();
void fetchNotifications() {
_notificationsRepository
.getNotificationList()
.then((List<NotificationElement> list) {
if (list.length > 0) {
_listNotifications.add(list);
} else {
_isEmptyList.add(true);
}
})
.catchError((e) => _handleErrorCase,
test: (e) => e is AuthorizationException)
.catchError((e) {
log.shout("Error occurred while fetching notifications $e");
_listNotifications.sink.addError("$e");
});
}
void _handleErrorCase(e) {
log.shout("Session invalid: $e");
_isLoggedIn.sink.add(false);
_listNotifications.sink.addError("Error");
}
}
This is what my repository code looks like:
notifications_repository.dart
import 'dart:async';
import 'package:logging/logging.dart';
import 'package:sunapsis/datasource/dataobjects/notification.dart';
import 'package:sunapsis/datasource/db/sunapsis_db_provider.dart';
import 'package:sunapsis/datasource/network/api_response.dart';
import 'package:sunapsis/datasource/network/sunapsis_api_provider.dart';
import 'package:sunapsis/utils/authorization_exception.dart';
/// Repository class which makes available all notifications related API functions
/// for server calls and database calls
class NotificationsRepository {
final Logger log = Logger('NotificationsRepository');
final SunapsisApiProvider apiProvider;
final SunapsisDbProvider dbProvider;
/// Optional [SunapsisApiProvider] and [SunapsisDbProvider] instances expected for unit testing
/// If instances are not provided - default case - a new instance is created
NotificationsRepository({SunapsisApiProvider api, SunapsisDbProvider db})
: apiProvider = api ?? SunapsisApiProvider(),
dbProvider = db ?? SunapsisDbProvider();
/// Returns a [Future] of [List] of [NotificationElement]
/// Tries to first look for notifications on the db
/// if notifications are found that list is returned
/// else a server call is made to fetch notifications
Future<List<NotificationElement>> getNotificationList([int currentTime]) {
return dbProvider.fetchNotifications().then(
(List<NotificationElement> notifications) {
if (notifications.length == 0) {
return getNotificationsListFromServer(currentTime);
}
return notifications;
}, onError: (_) {
return getNotificationsListFromServer(currentTime);
});
}
}
The function getNotificationsListFromServer is supposed to throw the AuthorizationException, which is supposed to be propagated through getNotificationList
This is the test case that is failing with the error mentioned before:
test('getNotification observable gets error on AuthorizationException',
() async {
when(mockNotificationsRepository.getNotificationList())
.thenThrow(AuthorizationException("test error", "test description"));
scheduleMicrotask(() => notificationBloc.fetchNotifications());
await expectLater(
notificationBloc.getNotificationList, emitsError("Error"));
});
And this is what the custom exception looks like:
authorization_exception.dart
class AuthorizationException implements Exception {
final String error;
final String description;
AuthorizationException(this.error, this.description);
String toString() {
var header = 'sunapsis Authorization error ($error)';
if (description != null) {
header = '$header: $description';
}
return '$header';
}
}
PS: When I tested my repository class and the function throwing the custom exception those tests were passed.
test('throws AuthorizationException on invalidSession()', () async {
when(mockSunapsisDbProvider.fetchNotifications())
.thenAnswer((_) => Future.error("Error"));
when(mockSunapsisDbProvider.getCachedLoginSession(1536333713))
.thenAnswer((_) => Future.value(authorization));
when(mockSunapsisApiProvider.getNotifications(authHeader))
.thenAnswer((_) => Future.value(ApiResponse.invalidSession()));
expect(notificationsRepository.getNotificationList(1536333713),
throwsA(TypeMatcher<AuthorizationException>()));
});
Above test passed and works as expected.
I am a new college grad working my first full time role and I might be doing something wrong. I will really appreciate any feedback or help, everything helps. Thanks for looking into this question.
You're using thenThrow to throw an exception, but because the mocked method returns a Future you should use thenAnswer.
The test would be like that:
test('getNotification observable gets error on AuthorizationException', () async {
// Using thenAnswer to throw an exception:
when(mockNotificationsRepository.getNotificationList())
.thenAnswer((_) async => throw AuthorizationException("test error", "test description"));
scheduleMicrotask(() => notificationBloc.fetchNotifications());
await expectLater(notificationBloc.getNotificationList, emitsError("Error"));
});
I think you are using the wrong TypeMatcher class. You need to use the one from the testing framework and not the one from the Flutter framework.
import 'package:flutter_test/flutter_test.dart';
import 'package:matcher/matcher.dart';
class AuthorizationException implements Exception {
const AuthorizationException();
}
Future<List<String>> getNotificationList(int id) async {
throw AuthorizationException();
}
void main() {
test('getNotification observable gets error on AuthorizationException',
() async {
expect(getNotificationList(1536333713),
throwsA(const TypeMatcher<AuthorizationException>()));
});
}
See this simple class and method:
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart';
import 'package:angular/angular.dart';
#Injectable()
class ApiClient {
final Client _http;
static final _headers = { 'Content-Type': 'application/json' };
static final _encodedHeaders = { 'Content-Type': 'application/x-www-form-urlencoded' };
ApiClient(this._http);
Future<T> get<T>(String url, T f(dynamic e)) async {
try {
final response = await _http.get(url);
var data = JSON.decode(response.body);
print(data);
if(data == null)return null;
final ts = f(data);
return ts;
} catch (e) {
_handleError(e);
return null;
}
}
}
It causes this error:
Unexpected token 'Future'.
Future get(String url, T f(dynamic e)) async {
^^^^^^
and when I rename the method say get1 the error goes away. Is this normal? I have other classes with method named get and works just fine. Am I missing something here?
See the issue on github
UPDATE:
It doesn't seem to me to be an identifier issue. Cause I can name a method get and there wouldn't be any error. Also, there is some built-in classes which have methods named get (e.g. Client class). It seems naming a generic-method to get causes the error: get<T>(). I agree with Vyacheslav Egorov - as said in comment, and I think this is a parser bug.
get is a built-in identifier to define a getter and should not be used as identifier
https://www.dartlang.org/guides/language/language-tour
I trying to use the dart.js call googlemap but receive "Breaking on exception: ReferenceError: ReceivePortSync is not defined". Anyone know about this exception?
import 'dart:html';
import 'dart:js';
import 'package:js/js.dart' as js;
import 'package:google_maps/google_maps.dart';
void main() {
bindMap();
}
void bindMap(){
js.scoped((){
final mapOptions = new MapOptions()
..zoom = 8
..center = new LatLng(-34.397, 150.644)
..mapTypeId = MapTypeId.ROADMAP
;
final map = new GMap(query("#map_canvas"), mapOptions);
});
}
You have to add <script src="packages/browser/interop.js"></script> in your html file and add browser package in dependencies.
On your code, you can :
avoid js.scoped that is not needed since few versions of js.
remove import 'dart:js'; that is not needed.
Finally you can have a look at the simple map example to have an up-to-date example.