i have a class with a Constructor and Async functions.
I have done module.exports so that i could call my Class from my GUI.js file and in my GUI.js file, i have required that class, and everything works fine.
But inside my class, im trying to do this ipcRenderer.send('message', 'Hello');
And im getting this error:
TypeError: Cannot read property 'send' of undefined
is it possible to remote the ipcRenderer in my GUI.js?
Thanks.
i have required the module in my main file, and in my renderer file it sends ipcRenderer.send('startMyClass');
And in my Main file: ipcMain.on('startMyClass', (event, args) => {
const client = new myClass();
client.Start();
})
This is my class/index.js file that is being required in my main file.
const request = require('request-promise');
const cheerio = require('cheerio');
const { ipcRenderer } = require('electron')
class myClass {
constructor() {
this._jar = request.jar();
this._request = request.defaults({ jar: this._jar });
}
async Start() {
await this.Test();
};
async Test() {
ipcRenderer.send('myMessage', 'Hello');
}
}
module.exports = myClass;
EDIT:
If i dont require it, and have the whole class in my main file, i can do event.sender.send('myMSG', 'hello');
But i want to do it in my class, that's NOT in the same file as my main.
Sending message from Main to Renderer should be done by sending to a specific webContents. That's why event.sender.send('myMSG', 'hello') works, while ipcRenderer.send not. The latter sends from Renderer to Main as stated in docs (and also, cannot be accessed from Main process as your Error told you it's undefined).
As explainded in ipcMain's docs you should access the webContents you want to send to and call send on that.
So to correct your code you can
Pass a reference to the main window to myClass and call send on that
class myClass {
constructor(args) {
// ...
this.mainWindow = args.win
}
// ...
async Test() {
this.mainWindow.webContents.send('myMessage', 'Hello');
}
}
Or send to the actually focused window (BrowserWindow.getFocusedWindow()) if that fits your needs
class myClass {
// ...
async Test() {
BrowserWindow.getFocusedWindow().webContents.send('myMessage', 'Hello');
}
}
Related
Let's assume that an initialization of MyComponent in Dart requires sending an HttpRequest to the server. Is it possible to construct an object synchronously and defer a 'real' initialization till the response come back?
In the example below, the _init() function is not called until "done" is printed. Is it possible to fix this?
import 'dart:async';
import 'dart:io';
class MyComponent{
MyComponent() {
_init();
}
Future _init() async {
print("init");
}
}
void main() {
var c = new MyComponent();
sleep(const Duration(seconds: 1));
print("done");
}
Output:
done
init
Probably the best way to handle this is with a factory function, which calls a private constructor.
In Dart, private methods start with an underscore, and "additional" constructors require a name in the form ClassName.constructorName, since Dart doesn't support function overloading. This means that private constructors require a name, which starts with an underscore (MyComponent._create in the below example).
import 'dart:async';
import 'dart:io';
class MyComponent{
/// Private constructor
MyComponent._create() {
print("_create() (private constructor)");
// Do most of your initialization here, that's what a constructor is for
//...
}
/// Public factory
static Future<MyComponent> create() async {
print("create() (public factory)");
// Call the private constructor
var component = MyComponent._create();
// Do initialization that requires async
//await component._complexAsyncInit();
// Return the fully initialized object
return component;
}
}
void main() async {
var c = await MyComponent.create();
print("done");
}
This way, it's impossible to accidentally create an improperly initialized object out of the class. The only available constructor is private, so the only way to create an object is with the factory, which performs proper initialization.
A constructor can only return an instance of the class it is a constructor of (MyComponent). Your requirement would require a constructor to return Future<MyComponent> which is not supported.
You either need to make an explicit initialization method that needs to be called by the user of your class like:
class MyComponent{
MyComponent();
Future init() async {
print("init");
}
}
void main() async {
var c = new MyComponent();
await c.init();
print("done");
}
or you start initialization in the consturctor and allow the user of the component to wait for initialization to be done.
class MyComponent{
Future _doneFuture;
MyComponent() {
_doneFuture = _init();
}
Future _init() async {
print("init");
}
Future get initializationDone => _doneFuture
}
void main() async {
var c = new MyComponent();
await c.initializationDone;
print("done");
}
When _doneFuture was already completed await c.initializationDone returns immediately otherwise it waits for the future to complete first.
I agree, an asynchronous factory function would help Dart devs with this problem. #kankaristo has IMHO given the best answer, a static async method that returns a fully constructed and initialized object. You have to deal with the async somehow, and breaking the init in two will lead to bugs.
I'm trying to create a decorator that requires dependency injection.
For example:
#Injectable()
class UserService{
#TimeoutAndCache(1000)
async getUser(id:string):Promise<User>{
// Make a call to db to get all Users
}
}
The #TimeoutAndCache returns a new promise which does the following:
if call takes longer than 1000ms, returns a rejection and when the call completes, it stores to redis (so that it can be fetched next time).
If call takes less than 1000ms, simply returns the result
export const TimeoutAndCache = function timeoutCache(ts: number, namespace) {
return function log(
target: object,
propertyKey: string,
descriptor: TypedPropertyDescriptor<any>,
) {
const originalMethod = descriptor.value; // save a reference to the original method
descriptor.value = function(...args: any[]) {
// pre
let timedOut = false;
// run and store result
const result: Promise<object> = originalMethod.apply(this, args);
const task = new Promise((resolve, reject) => {
const timer = setTimeout(() => {
if (!timedOut) {
timedOut = true;
console.log('timed out before finishing');
reject('timedout');
}
}, ts);
result.then(res => {
if (timedOut) {
// store in cache
console.log('store in cache');
} else {
clearTimeout(timer);
// return the result
resolve(res);
}
});
});
return task;
};
return descriptor;
};
};
I need to inject a RedisService to save the evaluated result.
One way I could inject Redis Service in to the UserService, but seems kind ugly.
You should consider using an Interceptor instead of a custom decorator as they run earlier in the Nest pipeline and support dependency injection by default.
However, because you want to both pass values (for cache timeout) as well as resolve dependencies you'll have to use the mixin pattern.
import {
ExecutionContext,
Injectable,
mixin,
NestInterceptor,
} from '#nestjs/common';
import { Observable } from 'rxjs';
import { TestService } from './test/test.service';
#Injectable()
export abstract class CacheInterceptor implements NestInterceptor {
protected abstract readonly cacheDuration: number;
constructor(private readonly testService: TestService) {}
intercept(
context: ExecutionContext,
call$: Observable<any>,
): Observable<any> {
// Whatever your logic needs to be
return call$;
}
}
export const makeCacheInterceptor = (cacheDuration: number) =>
mixin(
// tslint:disable-next-line:max-classes-per-file
class extends CacheInterceptor {
protected readonly cacheDuration = cacheDuration;
},
);
You would then be able to apply the Interceptor to your handler in a similar fashion:
#Injectable()
class UserService{
#UseInterceptors(makeCacheInterceptor(1000))
async getUser(id:string):Promise<User>{
// Make a call to db to get all Users
}
}
I'm trying to create a dart implementation of the auth0 javascript API using the js package from https://pub.dartlang.org/packages/js.
so I'm loading https://cdn.auth0.com/js/lock/10.0.0/lock.min.js in the index.html and I created the following auth0lock dart class:
#JS()
library auth0lock;
import 'package:js/js.dart';
#JS('Auth0Lock')
class Auth0LockJS {
external factory Auth0LockJS(String token, String domain, Object options);
external on(String event, Function func);
external show();
}
class Auth0Lock {
Auth0LockJS auth0;
Auth0Lock(String token, String domain, Object options) {
this.auth0 = new Auth0LockJS(token,domain,options);
}
on(String event, Function func) {
this.auth0.on(event,allowInterop(func));
}
show() {
this.auth0.show();
}
}
#anonymous
#JS()
class AuthResult {
external factory AuthResult({
String accessToken,
String idToken,
String idTokenPayload,
String state
});
external String get accessToken;
external set accessToken(String v);
external String get idToken;
external set idToken(String v);
external Object get idTokenPayload;
external set idTokenPayload(Object v);
external String get state;
external set state(String v);
}
I'm writing an angular2-dart application so I created an authentication service that uses the auth0lock.dart file that I showed previously using the following code:
#Injectable()
class Auth {
Auth0Lock lock;
authenticatedEvent(AuthResult authResult) {
print(authResult);
}
Auth() {
this.lock = new Auth0Lock(configObj.auth0.apiKey, configObj.auth0.domain,{});
this.lock.on("authenticated", authenticatedEvent);
}
updateProfileName(data) {
var profile = data['profile'] != null ? data['profile'] : data;
print(profile['name']);
}
authenticated() {
return false;
}
login() {
this.lock.show();
}
}
now... everything actually works! I created in the auth_service.dart file a variable typed AuthLock named lock. I instance is with parameters, run the show() function, connect to the authenticated event and the function is fired with the authentication is completed.
I created a class AuthResult but it ignores it and I get a javascript object returned from the function handler.
I program the code using Intellij and execute with dartium. so when I place a breakpoint on the print(authResult);line in the auth_service.dart file, the debugger shows that the authResult Object contains 2 properties, JavaScript View of type Object and class of type JSObjectimpl. the Javascript View contains all the properties that are returned by this function handler.
how do I convert it to a regular class in dart ? obviously I created the AuthResult class wrong cause the function handler doesn't return this type. so what am I missing?
thanks!
update
inside the authenticatedEvent function I tried printing authResult.values, that produced the error that a class of type JSObjectImpl doesn't have that function. so the return object is type JSObjectImpl. the weird thing is that I have no idea where JSObjectImpl is defined so I removed the variable type of authResult and tried to use the variables inside directory with the following code:
authenticatedEvent(authResult) {
var a = authResult.accessToken;
print(a);
}
this works. why I can't find JSObjectImpl type in dart? any quick way to convert this to a dart class?
thanks
Perhaps you just need to remove #anonymous from AuthResult
A simplified but complete and similar example
index.html
<!doctype html>
<html>
<head>
<script>
var Apple = function(type) {
this.type = type;
this.color = "red";
this.getInfo2 = function() {
return this.color + ' ' + this.type + ' apple';
};
};
Apple.prototype.getInfo = function() {
return this.color + ' ' + this.type + ' apple';
};
function callback(f) {
console.log(f);
f(new Apple('Golden Delicious'));
}
</script>
</head>
<body>
<script type="application/dart" src="index.dart"></script>
<script src="packages/browser/dart.js"></script>
</body>
</html>
index.dart
#JS()
library typed_callback.web;
import 'package:js/js.dart';
#JS()
class Apple {
external String get type;
external set type(String type);
external String get color;
external set color(String color);
external String getInfo();
external String getInfo2();
external Apple(String type);
}
typedef void Callback(Apple a);
#JS('callback')
external void callback(Callback /* or just Function */ f);
f(Apple apple) {
print(apple.getInfo());
print(apple); // prints the stringified JS object [object Object]
}
main() async {
callback(allowInterop(f));
}
I'm a bit confused about how AngularDart / DI instantiates new objects.
If I instantiate 'appcontroller' via HTML it never gets the catchError (it fails in the console with 'Uncaught Error...'). The odd thing is - this happens ONLY if I bind(Proxy, toValue: new Proxy()); if I bind(Proxy); it works!
Another way to make it work is to make the completer in Proxy static.Then bind(SyncProxy,toValue: new SyncProxy()); is no problem and catchError comes.
If I run Controller, Proxy and Module in a unit-test it works too...
#angular.Controller(selector: '[appcontroller]', publishAs: "ctrl")
class Controller {
final Logger _logger = new Logger("integration.test.Angular.Controller");
final Proxy _proxy;
bool _loadedWithError = false;
Controller(this._proxy) {
_proxy.load().catchError((final String error) {
_logger.severe("Error X: $error");
_loadedWithError = true;
});
}
}
#angular.Injectable()
class Proxy {
final Completer<bool> _completer = new Completer<bool>();
Future<bool> load() {
//_completer.completeError("Error");
new Timer(new Duration(seconds: 1),() {
_completer.completeError("Error");
});
return _completer.future;
}
}
class SampleModule extends angular.Module {
SampleModule() {
bind(Controller);
// works for UNIT-Test but fails with HTML instantiation
bind(Proxy, toValue: new Proxy());
}
}
main() {
applicationFactory().addModule(new SampleModule()).run();
}
HTML-Code:
<body appcontroller>
...
[ Update ]
According to Günters answer below and my own tests the approach bind(Proxy,toValue: new Proxy()); to create a Singleton is useless and counter-productive.
The normal bind is enough and avoids the Zone-Problem!
I need to access a JavaScript object's this from a Dart function. I'm effectively adding a new method to a JavaScript object, via Dart-JS interop. I need to access properties that are on the JavaScript object from the method defined in Dart.
The Callback constructor can pass the this from JavaScript. According to the API docs for Callback:
new Callback.many(Function f, {bool withThis: false})
new Callback.once(Function f, {bool withThis: false})
Here is an example:
Dart code:
import 'dart:html';
import 'package:js/js.dart' as js;
void main() {
var greeter = js.context['greeter'];
var msg = greeter['greet']('Bob');
greeter['doCoolStuff'] = new js.Callback.many(doCoolStuff, withThis: true);
}
doCoolStuff(jsThis) {
print(jsThis['msg']);
}
Notice the use of withThis: true when creating the Callback. The this from JavaScript is passed in as the first argument to the callback function. In this case, I give it a name of jsThis.
JavaScript code:
function Greeter() {
this.msg = 'hello';
var that = this;
document.getElementById('clickme').addEventListener('click', function() {
that.doCoolStuff();
});
}
Greeter.prototype.greet = function(name) {
return this.msg + ' ' + name;
}
var greeter = new Greeter();
document.getElementById('clickme').addEventListener('click', function() {
greeter.doCoolStuff(); // comes from Dart land
});