在构造函数中进行 GWT 异步回调安全吗?
Posted
技术标签:
【中文标题】在构造函数中进行 GWT 异步回调安全吗?【英文标题】:Is making a GWT asynccallback in a constructor safe? 【发布时间】:2013-04-08 07:46:51 【问题描述】:假设构造函数在代码的客户端部分(被翻译成 javascript 的部分)中运行。 回调方法 onSuccess 确实修改了类的实例变量。 回调被实现为匿名类,因此可以使用 OuterClass.this 访问外部类的实例。
通常在纯 Java 中我们不应该这样做,因为这样做,'this' 引用可以在对象构造完成之前逃逸。
但它也适用于将 Java 代码转换为 Javascript 的情况吗?我假设 javascript 代码是由网络浏览器中的单个线程执行的,所以这应该不是问题(单线程 => 没有可见性问题)?
【问题讨论】:
【参考方案1】:一方面,您是对的 - 问题不能由单独的线程触发,因为 JavaScript 是单线程的。
回调事件肯定会由在当前事件处理程序(构造当前对象的事件处理程序)完成后启动的事件处理程序来处理。所以他们只会看到完全构造的对象。
另一方面,您通常不需要线程来利用基本问题。这是一个简单的例子:
final A a = new A();
final B b = new B(a);
public class A
private B b;
public void setB(final B b)
this.b = b;
public void letBSaySomething()
b.saySomething();
public class B
private A a;
private final int some;
public B(final A a)
this.a = a;
a.setB(this);
a.letBSaySomething();
some = 55;
a.letBSaySomething();
public void saySomething()
RootPanel.get().add(new Label("Hello " + some));
这会导致输出
Hello 0
Hello 55
(尽管 'some' 是最终的)。这在 GWT(已编译/未编译)和纯 Java 程序中都会发生。
【讨论】:
【参考方案2】:AsyncCallback 本身只是一个类。在生产模式下发送 RPC 请求时,保证结果会通过 XmlHttpRequest 异步传入;在已编译的 javascript 中,在构造完成之前泄漏引用是 100% 不可能的,因为回调将在单独的 javascript 执行堆栈中被调用。
然而,在 gwt-dev 模式下,应该是异步的事情并不总是这样。就个人而言,我放弃了 gwt-dev 而不是 super-dev-mode,并且仅在我确实需要 java 调试器时才使用 gwt-dev,所以我无法确定它是否会不受构造问题的影响(测试它并找出来!)。
如果您没有在构造函数中发送任何请求,您将是 100% 安全的。如果您随后以不安全的方式访问 OuterClass.this,则仅创建异步回调只会导致问题,而不管涉及的类如何。
【讨论】:
以上是关于在构造函数中进行 GWT 异步回调安全吗?的主要内容,如果未能解决你的问题,请参考以下文章
在 GWT 异步回调中,如何在 onSuccess 中处理相同的返回类型?
sequelize.transaction() 可以将异步函数作为回调吗?