Как зарегистрировать обратный вызов JavaScript в апплете Java? - PullRequest
10 голосов
/ 17 ноября 2008

Я занимаюсь разработкой невидимого Java-апплета, который будет полностью управляться из JavaScript.

Я могу легко вызывать методы Java апплета и вызывать методы JavaScript из апплета с помощью netscape.javascript.JSObject.getWindow(this).call().

Но для регистрации обратного вызова JavaScript в апплете, я думаю, мне нужен какой-то объект функции JavaScript.

Я бы хотел сделать:

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

Который я мог бы вызвать из Javascript:

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

Так что я мог бы вызвать эту функцию в следующем коде:

func.call( ... );

Существует ли что-то подобное? Как я могу это сделать?

Rigth Теперь я думаю о создании некоторого Javascript для обработки этого механизма обратного вызова вместо того, чтобы делать это из апплета.

Ответы [ 3 ]

4 голосов
/ 13 августа 2012

Я понимаю, что это действительно старый вопрос, но он занял 2-е место в одном из моих поисков чего-то другого, и я думаю, что приведенное ниже может помочь кому-то еще, кто найдет это.

Недавно я сделал что-то подобное, в результате чего Java-апплет должен вызывать обратно в JavaScript по завершении задачи, вызывая различные функции в случае успеха или ошибки. Как было в последнее время, мне нужно было вызывать анонимные функции, определенные как параметры, передаваемые другим функциям. Это JavaScript на стороне клиента:

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

Как уже упоминалось в других ответах, Java может вызывать методы JavaScript только по имени. Это означает, что вам нужен глобальный метод обратного вызова, который затем может вызывать другие методы по мере необходимости:

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

Эта функция вызывается непосредственно из 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});
}

Вы можете удерживать ссылку на объект параметра, передаваемую бесконечно, если вы хотите использовать его в качестве некоторой формы зарегистрированного обратного вызова, а не одноразовой, если это необходимо, и т. Д.

В нашем случае обработка может занимать много времени, поэтому мы фактически раскручиваем другой поток - здесь также работают обратные вызовы:

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();
}
2 голосов
/ 17 ноября 2008

Я новичок в Java <-> JavaScript-общении, так как я планировал изучить его на этой неделе. Хорошая возможность здесь ...: -)

После некоторых тестов кажется, что вы не можете передать функцию JS апплету Java. Если я не делаю это неправильно ...

Я пытался:

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);
}

где Call определен как:

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);
}

Когда я передаю функцию JS (все тесты в FF3), я получаю нулевое значение на стороне Java.

Обратите внимание, что следующая процедура Java позволяет отображать код JS функции DumberTest!

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();
}

Кстати, я сделал функцию JS:

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

Я извлекаю имя функции JS из результата toString и передаю его апплету Java. Я не думаю, что мы можем обрабатывать анонимные функции, потому что Java вызывает функции JS по имени.

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);
}
1 голос
/ 18 ноября 2008

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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...