简体   繁体   English

如何在Java Applet中注册JavaScript回调?

[英]How to register a JavaScript callback in a Java Applet?

I'm developing an invisible Java Applet, that will be controlled entirely from JavaScript. 我正在开发一个不可见的Java Applet,它将完全由JavaScript控制。

I can call the applet's Java methods easily, and I can call JavaScript methods from within the applet by using netscape.javascript.JSObject.getWindow(this).call() . 我可以轻松调用applet的Java方法,也可以使用netscape.javascript.JSObject.getWindow(this).call()从applet内调用JavaScript方法。

But in order to register a JavaScript callback in the applet, I guess I would need an JavaScript function object of some sort. 但是,为了在小程序中注册JavaScript回调,我想我需要某种JavaScript函数对象。

I would like to do: 我想要做:

public void registerCallback( SomeJavascriptFunction func ) { ... }

Which I could call from Javascript: 我可以从Javascript调用:

myapplet.registerCallback(function(){ alert("called back"); });

So I could call this function in later code: 因此,我可以在以后的代码中调用此函数:

func.call( ... );

Does something like this exist? 是否存在这样的东西? How can I do this? 我怎样才能做到这一点?

Rigth now I'm thinking of creating some Javascript to handle this callback mechanism instead of doing so from the applet. 现在,Rigth正在考虑创建一些Javascript来处理此回调机制,而不是从applet中进行处理。

I realise this is a really old question, but it ranked 2nd in one of my searches for something else, and I think the below may help someone else that finds this. 我意识到这是一个非常老的问题,但是它在我搜索其他内容中排名第二,我认为以下内容可能会帮助其他人找到此问题。

I've recently done something similar whereby a Java applet needs to call back into JavaScript on completion of a task, calling different functions on success or error. 我最近做了类似的事情,一个Java applet需要在完成任务时回调JavaScript,在成功或出错时调用不同的函数。 As has been the trend over recent times, my needs were to call into anonymous functions defined as parameters being passed to other functions. 与最近的趋势一样,我的需求是调用匿名函数,这些函数定义为将参数传递给其他函数。 This is the javascript on the client side: 这是客户端上的javascript:

applet.DoProcessing({
    success: function(param) {
        alert('Success: ' + param);
    },
    error: function(param) {
        alert('Failed: ' + param);
    }
});

As mentioned in the other answers, Java can only call into JavaScript methods by name. 如其他答案所述,Java只能按名称调用JavaScript方法。 This means you need a global callback method, which can then call into other methods as need be: 这意味着您需要一个全局回调方法,然后可以根据需要调用其他方法:

function ProcessingCallback(isSuccessful, cbParam, jsObject) {
    if (isSuccessful && jsObject.success)
        jsObject.success(cbParam);
    else if (!isSuccessful && jsObject.error)
        jsObject.error(cbParam);
}

This function is called directly from within the Java applet: 从Java小程序内部直接调用此函数:

public void DoProcessing(final Object callbacks) {
   //do processing....


   JSObject w = JSObject.getWindow(this);
   //Call our named callback, note how we pass the callbacks parameter straight
   //back out again - it will be unchanged in javascript.
   w.call("ProcessingCallback", new Object[]{successful, output, callbacks});
}

You could hold on to the reference of the parameter object being passed in indefinitely if you wanted to use it as some form of registered callback rather than a throwaway one if need be etc. 如果要将参数对象用作某种形式的注册回调,而不是如果需要的话,则可以不加选择地保留对传入的参数对象的引用。

In our case the processing can be time intenstive, so we actually spin up another thread - the callbacks still work here also: 在我们的例子中,处理可能是时间密集的,因此我们实际上启动了另一个线程-回调在这里也仍然有效:

public void DoProcessing(final Object callbacks) {
    //hold a reference for use in the thread
    final Applet app = this;

    //Create a new Thread object to run our request asynchronously
    //so we can return back to single threaded javascript immediately
    Thread async = new Thread() {
        //Thread objects need a run method
        public void run() {
            //do processing....


            JSObject w = JSObject.getWindow(app);
            //Call our named callback, note how we pass the callbacks parameter
            //straight back out again - it will be unchanged in javascript.
            w.call("ProcessingCallback", new Object[]{successful, output, callbacks});
        }
    }
    //start the thread
    async.start();
}

I am brand new to Java <-> JavaScript communication, as I planned to explore it this week. 我本周计划进行探索,因此对Java <-> JavaScript通信是全新的。 A good opportunity here... :-) 这里的好机会... :-)

After some tests, it seems you cannot pass a JS function to a Java applet. 经过一些测试,似乎您无法将JS函数传递给Java小程序。 Unless I am doing it the wrong way... 除非我做错了方法...

I tried: 我试过了:

function CallJava()
{
  document.Applet.Call("Does it work?");
  document.Applet.Call(function () { alert("It works!"); });
  document.Applet.Call(DoSomething); // A simple parameterless JS function
  document.Applet.Call(window.location);
}
function DumbTest(message, value)
{
  alert("This is a dumb test with a message:\n" + message + "\n" + value);
}

where Call is (are) defined as: 呼叫定义为:

public void Call(String message)
{
  JSObject win = (JSObject) JSObject.getWindow(this);
  String[] arguments = { "Call with String", message };
  win.call("DumbTest", arguments);
}

public void Call(JSObject jso)
{
  JSObject win = (JSObject) JSObject.getWindow(this);
  String[] arguments = { "Call with JSObject", jso.toString() };
  win.call("DumbTest", arguments);
}

When I pass a JS function (all tests in FF3), I get a null on the Java side. 当我通过一个JS函数(FF3中的所有测试)时,我在Java端得到一个null。

Note that the following Java routine allows to display the JS code of DumberTest function! 请注意,以下Java例程允许显示DumberTest函数的JS代码!

public int Do()
{
  JSObject win = (JSObject) JSObject.getWindow(this);
  JSObject doc = (JSObject) win.getMember("document");
  JSObject fun = (JSObject) win.getMember("DumberTest");
  JSObject loc = (JSObject) doc.getMember("location");
  String href = (String) loc.getMember("href");
  String[] arguments = { href, fun.toString() };
  win.call("DumbTest", arguments);
  return fun.toString().length();
}

To the point: I made a JS function: 要点:我做了一个JS函数:

function RegisterCallback(cbFunction)
{
  var callback = cbFunction.toString(); // We get JS code
  var callbackName = /^function (\w+)\(/.exec(callback);
  document.Applet.RegisterCallback(callbackName[1]);
}

I extract the name of the JS function from the toString result and pass it to Java applet. 我从toString结果中提取JS函数的名称,并将其传递给Java applet。 I don't think we can handle anonymous functions because Java call JS functions by name. 我认为我们无法处理匿名函数,因为Java按名称调用JS函数。

Java side: Java方面:

String callbackFunction;
public void RegisterCallback(String functionName)
{
  callbackFunction = functionName;
}
void UseCallbackFunction()
{
    if (callbackFunction == null) return;
    JSObject win = (JSObject) JSObject.getWindow(this);
    win.call(callbackFunction, null);
}

win.eval() will call a predefined javascript. win.eval()将调用预定义的javascript。

String callbackFunction;
public void RegisterCallback(String functionName)
{
  callbackFunction = functionName;
}
void UseCallbackFunction()
{
    if (callbackFunction == null) return;
    JSObject win = (JSObject) JSObject.getWindow(this);
    win.eval(callbackFunction);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM