如何在 ScalaJS / PhantomJS 中使用 log4javascript
How to use log4javascript with ScalaJS / PhantomJS
我尝试 运行 使用 ScalaJS 和 PhantomJS 进行 log4javascript 并得到一个错误,使用 Rhino 它可以工作。
我采用了以下 ScalaJS 示例:https://github.com/scala-js/scalajs-tutorial
我从另一个 ScalaJS 示例中获取的 log4javascript:https://github.com/ochrons/scalajs-spa-tutorial
更具体地说,这 3 个文件:https://github.com/ochrons/scalajs-spa-tutorial/tree/master/client/src/main/scala/spatutorial/client/logger
我修改了 TutorialApp 以包含一些日志记录:
package tutorial.webapp
import scala.scalajs.js.JSApp
import org.scalajs.jquery.jQuery
import tutorial.logger.LoggerFactory
object TutorialApp extends JSApp {
println("Before getLogger...")
val log = LoggerFactory.getLogger(getClass().getName)
log.info("After getLogger...")
def main(): Unit = {
jQuery(setupUI _)
}
def setupUI(): Unit = {
jQuery("""<button type="button">Click me!</button>""")
.click(addClickedMessage _)
.appendTo(jQuery("body"))
jQuery("body").append("<p>Hello World</p>")
}
def addClickedMessage(): Unit = {
jQuery("body").append("<p>You clicked the button!</p>")
log.info("Button clicked...")
}
}
已修改build.sbt
enablePlugins(ScalaJSPlugin)
name := "Scala.js Tutorial"
scalaVersion := "2.11.7"
libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "0.8.1"
libraryDependencies += "be.doeraene" %%% "scalajs-jquery" % "0.8.0"
jsDependencies += RuntimeDOM
skip in packageJSDependencies := false
// uTest settings
libraryDependencies += "com.lihaoyi" %%% "utest" % "0.3.0" % "test"
testFrameworks += new TestFramework("utest.runner.Framework")
persistLauncher in Compile := true
persistLauncher in Test := false
// Modifications to original tutorial are here:
scalaJSStage in Global := FastOptStage // If NOT commented out: Uses Phantom, if IS commented out: Uses Rhino
libraryDependencies += "org.webjars" % "log4javascript" % "1.4.13"
jsDependencies += "org.webjars" % "log4javascript" % "1.4.13" / "1.4.13/log4javascript.js"
记录器文件在 src/main/scala/tutorial/logger 中,只有更改包名称才能编译它们。
修改 package.scala:
package tutorial
package object logger {
private val defaultLogger = LoggerFactory.getLogger("Log")
def log = defaultLogger
}
已修改 LoggerFactory.scala
package tutorial.logger
import scala.annotation.elidable
import scala.annotation.elidable._
trait Logger {
/*
* Use @elidable annotation to completely exclude functions from the compiler generated byte-code based on
* the specified level. In a production build most logging functions will simply disappear with no runtime
* performance penalty.
*
* Specify level as a compiler parameter
* > scalac -Xelide-below INFO
*/
@elidable(FINEST) def trace(msg: String, e: Exception): Unit
@elidable(FINEST) def trace(msg: String): Unit
@elidable(FINE) def debug(msg: String, e: Exception): Unit
@elidable(FINE) def debug(msg: String): Unit
@elidable(INFO) def info(msg: String, e: Exception): Unit
@elidable(INFO) def info(msg: String): Unit
@elidable(WARNING) def warn(msg: String, e: Exception): Unit
@elidable(WARNING) def warn(msg: String): Unit
@elidable(SEVERE) def error(msg: String, e: Exception): Unit
@elidable(SEVERE) def error(msg: String): Unit
@elidable(SEVERE) def fatal(msg: String, e: Exception): Unit
@elidable(SEVERE) def fatal(msg: String): Unit
def enableServerLogging(url: String): Unit
def disableServerLogging(): Unit
}
object LoggerFactory {
private[logger] def createLogger(name: String) = {}
lazy val consoleAppender = new BrowserConsoleAppender
lazy val popupAppender = new PopUpAppender
/**
* Create a logger that outputs to browser console
*/
def getLogger(name: String): Logger = {
val nativeLogger = Log4JavaScript.log4javascript.getLogger(name)
nativeLogger.addAppender(consoleAppender)
new L4JSLogger(nativeLogger)
}
/**
* Create a logger that outputs to a separate popup window
*/
def getPopUpLogger(name: String): Logger = {
val nativeLogger = Log4JavaScript.log4javascript.getLogger(name)
nativeLogger.addAppender(popupAppender)
new L4JSLogger(nativeLogger)
}
}
已修改Log4javascript.scala
package tutorial.logger
import scala.scalajs.js
import scala.scalajs.js.annotation.JSName
/**
* Facade for functions in log4javascript that we need
*/
@js.native
private[logger] trait Log4JavaScript extends js.Object {
def getLogger(name:js.UndefOr[String]):JSLogger = js.native
def setEnabled(enabled:Boolean):Unit = js.native
def isEnabled:Boolean = js.native
}
@js.native
@JSName("log4javascript.Level")
private[logger] trait Level extends js.Object {
val ALL:Level = js.native
val TRACE:Level = js.native
val DEBUG:Level = js.native
val INFO:Level = js.native
val WARN:Level = js.native
val ERROR:Level = js.native
val FATAL:Level = js.native
}
@js.native
@JSName("log4javascript.Logger")
private[logger] trait JSLogger extends js.Object {
def addAppender(appender:Appender):Unit = js.native
def removeAppender(appender:Appender):Unit = js.native
def removeAllAppenders(appender:Appender):Unit = js.native
def setLevel(level:Level):Unit = js.native
def getLevel:Level = js.native
def trace(msg:String, error:js.UndefOr[js.Error]):Unit = js.native
def debug(msg:String, error:js.UndefOr[js.Error]):Unit = js.native
def info(msg:String, error:js.UndefOr[js.Error]):Unit = js.native
def warn(msg:String, error:js.UndefOr[js.Error]):Unit = js.native
def error(msg:String, error:js.UndefOr[js.Error]):Unit = js.native
def fatal(msg:String, error:js.UndefOr[js.Error]):Unit = js.native
def trace(msg:String):Unit = js.native
def debug(msg:String):Unit = js.native
def info(msg:String):Unit = js.native
def warn(msg:String):Unit = js.native
def error(msg:String):Unit = js.native
def fatal(msg:String):Unit = js.native
}
@js.native
@JSName("log4javascript.Layout")
private[logger] trait Layout extends js.Object
@js.native
@JSName("log4javascript.JsonLayout")
private[logger] class JsonLayout extends Layout
@js.native
@JSName("log4javascript.Appender")
private[logger] trait Appender extends js.Object {
def setLayout(layout:Layout):Unit = js.native
def setThreshold(level:Level):Unit = js.native
}
@js.native
@JSName("log4javascript.BrowserConsoleAppender")
private[logger] class BrowserConsoleAppender extends Appender
@js.native
@JSName("log4javascript.PopUpAppender")
private[logger] class PopUpAppender extends Appender
@js.native
@JSName("log4javascript.AjaxAppender")
private[logger] class AjaxAppender(url:String) extends Appender {
def addHeader(header:String, value:String):Unit = js.native
}
@js.native
private[logger] object Log4JavaScript extends js.GlobalScope {
val log4javascript:Log4JavaScript = js.native
}
class L4JSLogger(jsLogger:JSLogger) extends Logger {
private var ajaxAppender:AjaxAppender = null
private def undefOrError(e:Exception):js.UndefOr[js.Error] = {
if(e == null)
js.undefined
else
e.asInstanceOf[js.Error]
}
override def trace(msg: String, e: Exception): Unit = jsLogger.trace(msg, undefOrError(e))
override def trace(msg: String): Unit = jsLogger.trace(msg)
override def debug(msg: String, e: Exception): Unit = jsLogger.debug(msg, undefOrError(e))
override def debug(msg: String): Unit = jsLogger.debug(msg)
override def info(msg: String, e: Exception): Unit = jsLogger.info(msg, undefOrError(e))
override def info(msg: String): Unit = jsLogger.info(msg)
override def warn(msg: String, e: Exception): Unit = jsLogger.warn(msg, undefOrError(e))
override def warn(msg: String): Unit = jsLogger.warn(msg)
override def error(msg: String, e: Exception): Unit = jsLogger.error(msg, undefOrError(e))
override def error(msg: String): Unit = jsLogger.error(msg)
override def fatal(msg: String, e: Exception): Unit = jsLogger.fatal(msg, undefOrError(e))
override def fatal(msg: String): Unit = jsLogger.fatal(msg)
override def enableServerLogging(url: String): Unit = {
if(ajaxAppender == null) {
ajaxAppender = new AjaxAppender(url)
ajaxAppender.addHeader("Content-Type", "application/json")
ajaxAppender.setLayout(new JsonLayout)
jsLogger.addAppender(ajaxAppender)
}
}
override def disableServerLogging():Unit = {
if(ajaxAppender != null) {
jsLogger.removeAppender(ajaxAppender)
ajaxAppender = null
}
}
}
当我尝试 sbt 运行 时,我收到以下错误消息:
> run
[info] Running tutorial.webapp.TutorialApp
Before getLogger...
TypeError: undefined is not an object (evaluating '$g["log4javascript"]["getLogger"]')
/tmp/phantomjs-launcher8416853343047081941.js:9 in onError
/tmp/phantomjs-launcher8416853343047081941.js:11 in onError
file:///home/jk/workspace/scalajs-tutorial-0.6.x/target/scala-2.11/scala-js-tutorial-fastopt.js:1085 (in function "getLogger__T__Ltutorial_logger_Logger")
/tmp/phantomjs-launcher8416853343047081941.js:13
file:///home/jk/workspace/scalajs-tutorial-0.6.x/target/scala-2.11/scala-js-tutorial-fastopt.js:1969 (in function "init___")
/tmp/phantomjs-launcher8416853343047081941.js:13
file:///home/jk/workspace/scalajs-tutorial-0.6.x/target/scala-2.11/scala-js-tutorial-fastopt.js:2005 (in function "$m_Ltutorial_webapp_TutorialApp$")
/tmp/phantomjs-launcher8416853343047081941.js:13
file:///tmp/phantomjs-launcher-webpage6476048362931659173.html:9541
/tmp/phantomjs-launcher8416853343047081941.js:13
org.scalajs.jsenv.ExternalJSEnv$NonZeroExitException: PhantomJS exited with code 2
at org.scalajs.jsenv.ExternalJSEnv$AbstractExtRunner.waitForVM(ExternalJSEnv.scala:96)
at org.scalajs.jsenv.ExternalJSEnv$ExtRunner.run(ExternalJSEnv.scala:143)
at org.scalajs.sbtplugin.ScalaJSPluginInternal$.org$scalajs$sbtplugin$ScalaJSPluginInternal$$jsRun(ScalaJSPluginInternal.scala:479)
at org.scalajs.sbtplugin.ScalaJSPluginInternal$$anonfun$$anonfun$apply$$anonfun$apply.apply(ScalaJSPluginInternal.scala:539)
at org.scalajs.sbtplugin.ScalaJSPluginInternal$$anonfun$$anonfun$apply$$anonfun$apply.apply(ScalaJSPluginInternal.scala:533)
at scala.Function1$$anonfun$compose.apply(Function1.scala:47)
[trace] Stack trace suppressed: run last compile:run for the full output.
[error] (compile:run) org.scalajs.jsenv.ExternalJSEnv$NonZeroExitException: PhantomJS exited with code 2
[error] Total time: 51 s, completed Jan 13, 2016 9:08:34 PM
sbt 测试也会失败,并显示相同的错误消息:TypeError: undefined is not an object (evaluating '$g["log4javascript"]["getLogger"]')
如果我在 build.sbt
中注释掉以下行
//scalaJSStage in Global := FastOptStage // If NOT commented out: Uses Phantom, if IS commented out: Uses Rhino
然后我从 sbt 运行:
得到以下结果
> run
[info] Running tutorial.webapp.TutorialApp
Before getLogger...
After getLogger...
[success] Total time: 4 s, completed Jan 13, 2016 9:16:39 PM
并且该脚本也适用于浏览器,当加载文件 scalajs-tutorial-fastopt.html 时,会出现按钮,单击时会在控制台上显示新的 "You clicked the button" 文本和 "Button clicked..."。 sbt 测试也成功。
幻影版本为2.0.1-开发。
如何使代码与 Phantom.js 一起工作?
已编辑:
我将 Phantom 降级到 2.0.0 版本,但错误消息保持不变。
我也运行关注这个问题,遵循相同的教程。结果发现问题的根本原因是在 log4javascript 代码中,有嵌入 html 的字符串(里面有更多 javascript )。我不知道这背后的原因可能是什么......无论如何,PhantomJS 测试 运行ner 的工作原理是将所有 js 代码和依赖项一起吐出到一个 html 文件中(在脚本中标签);当 javascript 解释器看到未转义的 </script>
标记时,它会出错。 (顺便说一句,我发现这个的方法是在我的临时文件中找到 phantomjs-launcher-*.html 页面并在 Chrome 中打开它)。
无论如何,在查看 log4javascript 的源代码并注意到它托管在 sourceforge 上并且大约 9 年没有更新(并且源代码控制是 CVS...)之后,我们决定使用不同的日志记录框架实现,因为能够 运行 在 PhantomJS 中进行测试对我们来说很重要。
非常令人沮丧,因为您有点希望日志记录框架成为 "just works"。
我尝试 运行 使用 ScalaJS 和 PhantomJS 进行 log4javascript 并得到一个错误,使用 Rhino 它可以工作。
我采用了以下 ScalaJS 示例:https://github.com/scala-js/scalajs-tutorial
我从另一个 ScalaJS 示例中获取的 log4javascript:https://github.com/ochrons/scalajs-spa-tutorial 更具体地说,这 3 个文件:https://github.com/ochrons/scalajs-spa-tutorial/tree/master/client/src/main/scala/spatutorial/client/logger
我修改了 TutorialApp 以包含一些日志记录:
package tutorial.webapp
import scala.scalajs.js.JSApp
import org.scalajs.jquery.jQuery
import tutorial.logger.LoggerFactory
object TutorialApp extends JSApp {
println("Before getLogger...")
val log = LoggerFactory.getLogger(getClass().getName)
log.info("After getLogger...")
def main(): Unit = {
jQuery(setupUI _)
}
def setupUI(): Unit = {
jQuery("""<button type="button">Click me!</button>""")
.click(addClickedMessage _)
.appendTo(jQuery("body"))
jQuery("body").append("<p>Hello World</p>")
}
def addClickedMessage(): Unit = {
jQuery("body").append("<p>You clicked the button!</p>")
log.info("Button clicked...")
}
}
已修改build.sbt
enablePlugins(ScalaJSPlugin)
name := "Scala.js Tutorial"
scalaVersion := "2.11.7"
libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "0.8.1"
libraryDependencies += "be.doeraene" %%% "scalajs-jquery" % "0.8.0"
jsDependencies += RuntimeDOM
skip in packageJSDependencies := false
// uTest settings
libraryDependencies += "com.lihaoyi" %%% "utest" % "0.3.0" % "test"
testFrameworks += new TestFramework("utest.runner.Framework")
persistLauncher in Compile := true
persistLauncher in Test := false
// Modifications to original tutorial are here:
scalaJSStage in Global := FastOptStage // If NOT commented out: Uses Phantom, if IS commented out: Uses Rhino
libraryDependencies += "org.webjars" % "log4javascript" % "1.4.13"
jsDependencies += "org.webjars" % "log4javascript" % "1.4.13" / "1.4.13/log4javascript.js"
记录器文件在 src/main/scala/tutorial/logger 中,只有更改包名称才能编译它们。 修改 package.scala:
package tutorial
package object logger {
private val defaultLogger = LoggerFactory.getLogger("Log")
def log = defaultLogger
}
已修改 LoggerFactory.scala
package tutorial.logger
import scala.annotation.elidable
import scala.annotation.elidable._
trait Logger {
/*
* Use @elidable annotation to completely exclude functions from the compiler generated byte-code based on
* the specified level. In a production build most logging functions will simply disappear with no runtime
* performance penalty.
*
* Specify level as a compiler parameter
* > scalac -Xelide-below INFO
*/
@elidable(FINEST) def trace(msg: String, e: Exception): Unit
@elidable(FINEST) def trace(msg: String): Unit
@elidable(FINE) def debug(msg: String, e: Exception): Unit
@elidable(FINE) def debug(msg: String): Unit
@elidable(INFO) def info(msg: String, e: Exception): Unit
@elidable(INFO) def info(msg: String): Unit
@elidable(WARNING) def warn(msg: String, e: Exception): Unit
@elidable(WARNING) def warn(msg: String): Unit
@elidable(SEVERE) def error(msg: String, e: Exception): Unit
@elidable(SEVERE) def error(msg: String): Unit
@elidable(SEVERE) def fatal(msg: String, e: Exception): Unit
@elidable(SEVERE) def fatal(msg: String): Unit
def enableServerLogging(url: String): Unit
def disableServerLogging(): Unit
}
object LoggerFactory {
private[logger] def createLogger(name: String) = {}
lazy val consoleAppender = new BrowserConsoleAppender
lazy val popupAppender = new PopUpAppender
/**
* Create a logger that outputs to browser console
*/
def getLogger(name: String): Logger = {
val nativeLogger = Log4JavaScript.log4javascript.getLogger(name)
nativeLogger.addAppender(consoleAppender)
new L4JSLogger(nativeLogger)
}
/**
* Create a logger that outputs to a separate popup window
*/
def getPopUpLogger(name: String): Logger = {
val nativeLogger = Log4JavaScript.log4javascript.getLogger(name)
nativeLogger.addAppender(popupAppender)
new L4JSLogger(nativeLogger)
}
}
已修改Log4javascript.scala
package tutorial.logger
import scala.scalajs.js
import scala.scalajs.js.annotation.JSName
/**
* Facade for functions in log4javascript that we need
*/
@js.native
private[logger] trait Log4JavaScript extends js.Object {
def getLogger(name:js.UndefOr[String]):JSLogger = js.native
def setEnabled(enabled:Boolean):Unit = js.native
def isEnabled:Boolean = js.native
}
@js.native
@JSName("log4javascript.Level")
private[logger] trait Level extends js.Object {
val ALL:Level = js.native
val TRACE:Level = js.native
val DEBUG:Level = js.native
val INFO:Level = js.native
val WARN:Level = js.native
val ERROR:Level = js.native
val FATAL:Level = js.native
}
@js.native
@JSName("log4javascript.Logger")
private[logger] trait JSLogger extends js.Object {
def addAppender(appender:Appender):Unit = js.native
def removeAppender(appender:Appender):Unit = js.native
def removeAllAppenders(appender:Appender):Unit = js.native
def setLevel(level:Level):Unit = js.native
def getLevel:Level = js.native
def trace(msg:String, error:js.UndefOr[js.Error]):Unit = js.native
def debug(msg:String, error:js.UndefOr[js.Error]):Unit = js.native
def info(msg:String, error:js.UndefOr[js.Error]):Unit = js.native
def warn(msg:String, error:js.UndefOr[js.Error]):Unit = js.native
def error(msg:String, error:js.UndefOr[js.Error]):Unit = js.native
def fatal(msg:String, error:js.UndefOr[js.Error]):Unit = js.native
def trace(msg:String):Unit = js.native
def debug(msg:String):Unit = js.native
def info(msg:String):Unit = js.native
def warn(msg:String):Unit = js.native
def error(msg:String):Unit = js.native
def fatal(msg:String):Unit = js.native
}
@js.native
@JSName("log4javascript.Layout")
private[logger] trait Layout extends js.Object
@js.native
@JSName("log4javascript.JsonLayout")
private[logger] class JsonLayout extends Layout
@js.native
@JSName("log4javascript.Appender")
private[logger] trait Appender extends js.Object {
def setLayout(layout:Layout):Unit = js.native
def setThreshold(level:Level):Unit = js.native
}
@js.native
@JSName("log4javascript.BrowserConsoleAppender")
private[logger] class BrowserConsoleAppender extends Appender
@js.native
@JSName("log4javascript.PopUpAppender")
private[logger] class PopUpAppender extends Appender
@js.native
@JSName("log4javascript.AjaxAppender")
private[logger] class AjaxAppender(url:String) extends Appender {
def addHeader(header:String, value:String):Unit = js.native
}
@js.native
private[logger] object Log4JavaScript extends js.GlobalScope {
val log4javascript:Log4JavaScript = js.native
}
class L4JSLogger(jsLogger:JSLogger) extends Logger {
private var ajaxAppender:AjaxAppender = null
private def undefOrError(e:Exception):js.UndefOr[js.Error] = {
if(e == null)
js.undefined
else
e.asInstanceOf[js.Error]
}
override def trace(msg: String, e: Exception): Unit = jsLogger.trace(msg, undefOrError(e))
override def trace(msg: String): Unit = jsLogger.trace(msg)
override def debug(msg: String, e: Exception): Unit = jsLogger.debug(msg, undefOrError(e))
override def debug(msg: String): Unit = jsLogger.debug(msg)
override def info(msg: String, e: Exception): Unit = jsLogger.info(msg, undefOrError(e))
override def info(msg: String): Unit = jsLogger.info(msg)
override def warn(msg: String, e: Exception): Unit = jsLogger.warn(msg, undefOrError(e))
override def warn(msg: String): Unit = jsLogger.warn(msg)
override def error(msg: String, e: Exception): Unit = jsLogger.error(msg, undefOrError(e))
override def error(msg: String): Unit = jsLogger.error(msg)
override def fatal(msg: String, e: Exception): Unit = jsLogger.fatal(msg, undefOrError(e))
override def fatal(msg: String): Unit = jsLogger.fatal(msg)
override def enableServerLogging(url: String): Unit = {
if(ajaxAppender == null) {
ajaxAppender = new AjaxAppender(url)
ajaxAppender.addHeader("Content-Type", "application/json")
ajaxAppender.setLayout(new JsonLayout)
jsLogger.addAppender(ajaxAppender)
}
}
override def disableServerLogging():Unit = {
if(ajaxAppender != null) {
jsLogger.removeAppender(ajaxAppender)
ajaxAppender = null
}
}
}
当我尝试 sbt 运行 时,我收到以下错误消息:
> run
[info] Running tutorial.webapp.TutorialApp
Before getLogger...
TypeError: undefined is not an object (evaluating '$g["log4javascript"]["getLogger"]')
/tmp/phantomjs-launcher8416853343047081941.js:9 in onError
/tmp/phantomjs-launcher8416853343047081941.js:11 in onError
file:///home/jk/workspace/scalajs-tutorial-0.6.x/target/scala-2.11/scala-js-tutorial-fastopt.js:1085 (in function "getLogger__T__Ltutorial_logger_Logger")
/tmp/phantomjs-launcher8416853343047081941.js:13
file:///home/jk/workspace/scalajs-tutorial-0.6.x/target/scala-2.11/scala-js-tutorial-fastopt.js:1969 (in function "init___")
/tmp/phantomjs-launcher8416853343047081941.js:13
file:///home/jk/workspace/scalajs-tutorial-0.6.x/target/scala-2.11/scala-js-tutorial-fastopt.js:2005 (in function "$m_Ltutorial_webapp_TutorialApp$")
/tmp/phantomjs-launcher8416853343047081941.js:13
file:///tmp/phantomjs-launcher-webpage6476048362931659173.html:9541
/tmp/phantomjs-launcher8416853343047081941.js:13
org.scalajs.jsenv.ExternalJSEnv$NonZeroExitException: PhantomJS exited with code 2
at org.scalajs.jsenv.ExternalJSEnv$AbstractExtRunner.waitForVM(ExternalJSEnv.scala:96)
at org.scalajs.jsenv.ExternalJSEnv$ExtRunner.run(ExternalJSEnv.scala:143)
at org.scalajs.sbtplugin.ScalaJSPluginInternal$.org$scalajs$sbtplugin$ScalaJSPluginInternal$$jsRun(ScalaJSPluginInternal.scala:479)
at org.scalajs.sbtplugin.ScalaJSPluginInternal$$anonfun$$anonfun$apply$$anonfun$apply.apply(ScalaJSPluginInternal.scala:539)
at org.scalajs.sbtplugin.ScalaJSPluginInternal$$anonfun$$anonfun$apply$$anonfun$apply.apply(ScalaJSPluginInternal.scala:533)
at scala.Function1$$anonfun$compose.apply(Function1.scala:47)
[trace] Stack trace suppressed: run last compile:run for the full output.
[error] (compile:run) org.scalajs.jsenv.ExternalJSEnv$NonZeroExitException: PhantomJS exited with code 2
[error] Total time: 51 s, completed Jan 13, 2016 9:08:34 PM
sbt 测试也会失败,并显示相同的错误消息:TypeError: undefined is not an object (evaluating '$g["log4javascript"]["getLogger"]')
如果我在 build.sbt
中注释掉以下行//scalaJSStage in Global := FastOptStage // If NOT commented out: Uses Phantom, if IS commented out: Uses Rhino
然后我从 sbt 运行:
得到以下结果> run
[info] Running tutorial.webapp.TutorialApp
Before getLogger...
After getLogger...
[success] Total time: 4 s, completed Jan 13, 2016 9:16:39 PM
并且该脚本也适用于浏览器,当加载文件 scalajs-tutorial-fastopt.html 时,会出现按钮,单击时会在控制台上显示新的 "You clicked the button" 文本和 "Button clicked..."。 sbt 测试也成功。
幻影版本为2.0.1-开发。
如何使代码与 Phantom.js 一起工作?
已编辑: 我将 Phantom 降级到 2.0.0 版本,但错误消息保持不变。
我也运行关注这个问题,遵循相同的教程。结果发现问题的根本原因是在 log4javascript 代码中,有嵌入 html 的字符串(里面有更多 javascript )。我不知道这背后的原因可能是什么......无论如何,PhantomJS 测试 运行ner 的工作原理是将所有 js 代码和依赖项一起吐出到一个 html 文件中(在脚本中标签);当 javascript 解释器看到未转义的 </script>
标记时,它会出错。 (顺便说一句,我发现这个的方法是在我的临时文件中找到 phantomjs-launcher-*.html 页面并在 Chrome 中打开它)。
无论如何,在查看 log4javascript 的源代码并注意到它托管在 sourceforge 上并且大约 9 年没有更新(并且源代码控制是 CVS...)之后,我们决定使用不同的日志记录框架实现,因为能够 运行 在 PhantomJS 中进行测试对我们来说很重要。
非常令人沮丧,因为您有点希望日志记录框架成为 "just works"。