如何使用 ECMAScript-6 从 GWT jsni 代码导入?

mic*_*ala 2 gwt ecmascript-6

所以,我知道在 GWT 中我可以编写纯 JavaScript 代码的 JSNI 代码。但是,不幸的是,如果我在其中使用 ES6 代码,JSNI 代码将无法编译。

这意味着,例如,我不能做这样的事情:

private native void jsniMethod(String jsModule) /*-{
    import(jsModule)
        .then(loadedModule => {
            doStuffWithLoadedModule(loadedModule);
        })
        .catch(err => alert(err));
}-*/;
Run Code Online (Sandbox Code Playgroud)

有没有办法在 GWT 代码中实现这一点?我的意思是,我需要对loadedModule的引用,这样我就可以在一些jsni代码中使用它(doStuffWithLoadedModule方法实现)。

谢谢!

Col*_*rth 5

这是不可能的。您需要将 JSNI 不支持的 JS 功能放入某种外部 JS 中,或者用与 JSNI 兼容的旧 JS 重写它们。考虑将 ScriptInjector 作为此选项或您的主机 html 页面的选项之一。

对于这个特定的事情,您只需要用函数替换箭头运算符:

private native void jsniMethod(String jsModule) /*-{
    import(jsModule)
        .then(function(loadedModule) {
            doStuffWithLoadedModule(loadedModule);
        })
        .catch(function(err) { alert(err) });
}-*/;
Run Code Online (Sandbox Code Playgroud)

作为替代方案,要使用 java lambda,您可以使用 JsInterop。请记住,这import实际上不是函数调用,而是 js 关键字,尽管这应该仍然有效:

@JsMethod(namespace = "<window>")
public native Promise<Object> import(String jsModuleName);
Run Code Online (Sandbox Code Playgroud)

然后,您可以调用它并传入 Java lambda:

private void notJsniMethod(String jsModule) {
    import(jsModule)
        .then(loadedModule -> {
            doStuffWithLoadedModule(loadedModule);
            return null;
        })
        .catch_(err -> {
            DomGlobal.alert(err.toString())
            return null;
        });

}
Run Code Online (Sandbox Code Playgroud)

与原来的 JS/JSNI 相比的变化:

  • =>已替换为 java 的->,其操作方式几乎相同
  • alert(...)现在是DomGlobal.alert(...),因为 java 没有“全局”名称空间
  • 显式return null是必需的,因为 java 不会让您在需要值时“忘记”返回值。
  • .catch(...)替换为.catch_(...), 因为 Java 不允许将关键字用作标识符