konsoletyper / teavm

Compiles Java bytecode to JavaScript, WebAssembly and C
https://teavm.org
Apache License 2.0
2.61k stars 263 forks source link

Handling a JS function that returns a Promise #941

Open XomaDev opened 3 weeks ago

XomaDev commented 3 weeks ago

Hello, thanks again for TeaVM. From past few hours, I'm trying to figure out a situation where my Java program immediately expects a value (from the JS). I learnt that TeaVM dosent support sleep() function. I did what I can after looking into the docs, such as:

@Async
public static native String stdInput();

private static void stdInput(AsyncCallback<String> callback) {
  stdInputAsync(callback::complete);
}
...
@SuppressWarnings("unused")
@JSFunctor
interface ICallback extends JSObject {
  void complete(String result);
}

My JS side code:

function stdInput(callback: (result: string) => void): void {
  callback("meow");
}

But it results in this error:

image

If I simply try to return a promise in stdInput(), I get an empty String at the Java side. Please help.

konsoletyper commented 3 weeks ago

I learnt that TeaVM dosent support sleep() function

What function do you mean? There aren't functions in Java, there are methods only

But it results in this error:

I don't have enough information about your code base and can't judge, but perhaps you are trying to run async code from within JavaScript event handler, which is prohibited. One possible workaround is start a new Thread from within JS event handler.

XomaDev commented 3 weeks ago

What function do you mean? There aren't functions in Java, there are methods only

Yes, I mean the Thread.sleep().

I don't have enough information about your code base and can't judge, but perhaps you are trying to run async code from within JavaScript event handler, which is prohibited. One possible workaround is start a new Thread from within JS event handler.

Hmm. All I'm trying to do is someway be able to give Java, a value, from JavaScript, immediately. Could you please guide me on how to approach this issue?

Thanks

Edit: By immediate I mean, Java needs to immediately consume a value that should be provided from JavaScript.

konsoletyper commented 3 weeks ago

Yes, I mean the Thread.sleep()

It's supported in TeaVM: https://teavm.org/jcl-report/recent/classes/java.lang.Thread.html

Hmm. All I'm trying to do is someway be able to give Java, a value, from JavaScript, immediately. Could you please guide me on how to approach this issue?

There's no way to do something "immediately" with a promise. Promise only resolves eventually, and you can't influence that.

Anyway, I'll try to clarify. Your @Async code LGTM, at least parts that you provided. And I suppose I understand you intention: you want to create a terminal emulator. But from stack trace you provided I can't see everything. I can only assume that somewhere below there's call from native browser event handler, right? In this case you should wrap this event handler with a new Thread. For example, if there was code like:

button.onClick(e -> {
   doSomething();
});

you need following:

button.onClick(e -> {
   var thread = new Thread(() -> doSomething());
   thread.start();
});