You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Slinky/Scala.js环境中调用异步函数导致渲染失败

Scala.js + Slinky Native 异步调用报错问题解决

问题背景

不确定该问题属于Scala.js通用问题,还是Slinky/Slinky-native/Slinky-hot的特定问题。使用的依赖如下:

libraryDependencies += "me.shadaj" %%% "slinky-native" % "0.7.0"
libraryDependencies += "me.shadaj" %%% "slinky-hot" % "0.7.0"

addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.10.1")

代码实现

编写了用于获取Facebook登录状态的异步函数:

object LoginController {
    def userFBLoginStatus: Future[LoginStatus] = {
      FBAccessToken.getCurrentAccessToken.toFuture.map {

其中调用的JavaScript库静态函数定义如下:

@native
  @JSImport("react-native-fbsdk-next", JSImport.Default)
  object FBAccessToken extends js.Object {
    def getCurrentAccessToken: Promise[FBAccessToken | Null] = native
  }

在主App组件中调用该异步函数:

@react class App extends Component {
  type Props = Unit
  type State = Boolean

  def initialState = false


  override def componentDidMount(): Unit = {
    LoginController.userFBLoginStatus.map {
      case LoggedIn => setState(true)
      case LoggedOut => setState(false)
    }
  }

  override def render(): ReactElement = {
    if (state)
      View(//welcome view)
    else
      View(//login page view)

报错情况

预期通过componentDidMount中的异步函数返回结果切换视图,sbt clean fastOptJS执行无异常,但应用渲染时出现以下报错:

TypeError: undefined is not an object (evaluating 'this$.then')
This error is located at:
    in App$ (at renderApplication.js:50)
    in RCTView (at View.js:32)
    in View (at AppContainer.js:92)
    in RCTView (at View.js:32)
    in View (at AppContainer.js:119)
    in AppContainer (at renderApplication.js:43)
    in DanceApp(RootComponent) (at renderApplication.js:60)
 ERROR  TypeError: undefined is not an object (evaluating 'this$.then')

注释掉componentDidMount中的异步调用后,渲染恢复正常。从报错信息(evaluating 'this$.then')推断,问题出在Promise的then方法调用上,可能是获取到的对象并非预期的Promise实例。

等价的React JavaScript代码可以正常运行:

class Map extends Component {
  constructor () {
    super()
    this.state = { wells: [] }
  }

  componentDidMount() {
    this.props.fetchWells()
      .then(res => this.setState({ wells: res.wells }) )
  }

  render () {
    const { wells } = this.state
    return wells.length ? this.renderWells() : (
      <span>Loading wells...</span>
    )
  }
}

解决方案

修改JSImport的导入方式,将默认导出改为指定具体的导出名称AccessToken,问题解决。修改后的代码如下:

@native
  @JSImport("react-native-fbsdk-next", "AccessToken")
  object FBAccessToken extends js.Object {
    def getCurrentAccessToken(): Promise[FBAccessToken | Null] = native
  }

内容的提问来源于stack exchange,提问作者arinray

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 04:35:25