Как я могу объединить этот контекст с invokeFunction в Nashorn? - PullRequest
0 голосов
/ 06 мая 2019

Я пытаюсь вызвать функцию в Javascript из Java / Nashorn (в Scala, но это не существенно для вопроса).

// JS
var foo = function(calculator){  // calculator is a Scala object
  return this.num * calculator.calcMult();
}

Контекст на стороне Scala выглядит следующим образом:

case class Thing(
  num: Int,
  stuff: String
)

case class Worker() {  // Scala object to bind to calculator
  def calMult() = { 3 }  // presumably some complex computation here
}

Я начинаю с получения foo в среду JS:

jsengine.eval("""var foo = function(calculator){return this.num * calculator.calcMult();}"""

Чтобы использовать это, мне нужны две вещи: 1) контекст «this», который будет заполнен моим объектом Thing, и 2) возможность передавать объект Java / Scala в мою функцию JS (чтобы позже вызвать calcMulti) , (При необходимости я могу легко JSON-сериализовать Thing.)

Как я могу сделать оба и успешно вызвать foo () из Scala?

1 Ответ

0 голосов
/ 11 мая 2019

Возможно, это не единственное или самое чистое решение, но оно работает.

Оказывается, у javascript есть возможность привязать заданный контекст "this" к функции, которая создает "связанную функцию", в которой ваше "this" видно внутри. Затем вы используете invoke (), как обычно, для связанной функции.

val inv = javascript.asInstanceOf[Invocable]
val myThis: String = // JSON serialized Map of stuff you want accessible in the js function

val bindFn = "bind_" + fnName
javascript.eval(bindFn + s" = $fnName.bind(" + myThis + ")")

inv.invokeFunction(bindFn, args: _*)

Если вы передали myThis в привязку для включения {"x":"foo"}, то при вызове любой доступ в вашей функции к this.x преобразуется в "foo", как и следовало ожидать.

...