You're looking for the dart:js
library.
You need to basically use allowInterop
and the @JS()
notation.
Setup
The Promise
class
You define a custom Promise
class using the @JS
annotation. This is necessary to create a promise instance that can be used from JavaScript to interact with Dart asynchronous code:
@JS('Promise')
class Promise<T> {
external Promise(void executor(void resolve(T result), Function reject));
external Promise then(void onFulfilled(T result), [Function onRejected]);
}
For your example - LoginClass
class LoginResponse {
int userId;
int id;
LoginResponse(this.userId, this.id);
}
Dio and request setup
final _dio = Dio();
Future<LoginResponse> login() async {
// _dio.get("URL")
return LoginResponse(
response.data['userId'],
response.data['id'],
);
}
Perform login
The performLogin
function wraps the login process in a promise, allowing it to be accessed from JavaScript:
Promise performLogin() {
return Promise(js.allowInterop((resolve, reject) {
login().then((value) {
final jsonMap = {
'userId': value.userId,
'id': value.id,
};
final jsonString = jsonEncode(jsonMap);
resolve(jsonString);
}).catchError((error) {
reject(error);
});
}));
}
Binding performLogin
to Javascript Window
Object:
You use the setProperty
function from the js_util
library to bind the performLogin
function to the window
object. This makes it accessible from the browser console:
void main() {
setProperty(window, 'performLogin', js.allowInterop(performLogin));
}
Calling the code within the Browser console
You can now use:
performLogin().then(result => {
// You need to convert the result to JSON
const userData = JSON.parse(result);
console.log('userId: ', userData.userId);
console.log("ID: ", userData.id);
});
Result

Putting it all together
Here's the complete code as a runnable snippet
import 'dart:html';
import 'dart:js' as js;
import 'dart:js_interop';
import 'package:js/js_util.dart';
import 'package:dio/dio.dart';
import 'dart:convert';
@JS('Promise')
class Promise<T> {
external Promise(void executor(void resolve(T result), Function reject));
external Promise then(void onFulfilled(T result), [Function onRejected]);
}
class LoginResponse {
int userId;
int id;
LoginResponse(this.userId, this.id);
}
final _dio = Dio();
Future<LoginResponse> login() async {
Response response = await _dio.get(
"https://jsonplaceholder.typicode.com/posts/1",
options: Options(validateStatus: (status) => status! < 500),
);
return LoginResponse(
response.data['userId'],
response.data['id'],
);
}
Promise performLogin() {
return Promise(js.allowInterop((resolve, reject) {
login().then((value) {
final jsonMap = {
'userId': value.userId,
'id': value.id,
};
final jsonString = jsonEncode(jsonMap);
resolve(jsonString);
}).catchError((error) {
reject(error);
});
}));
}
void main() {
setProperty(window, 'performLogin', js.allowInterop(performLogin));
}
See also