Web Socket Problem with Javascript and Java – Uncaught DOMException: An attempt was made to use an object that is not, or is no longer, usable

huangapple go评论106阅读模式
英文:

Web Socket Problem with Javascript and Java - Uncaught DOMException: An attempt was made to use an object that is not, or is no longer, usable

问题

我正在尝试在 JavaScript 和 Java 之间建立一个 WebSocket 连接,但我得到了以下错误信息:
<br/>
Uncaught DOMException: 尝试使用一个不可用的对象或不再可用的对象 <br/>
我是根据互联网上的一些示例来做的。有人知道可能是什么原因吗?<br/>
项目名称是 Teste-1

<br/>JS 代码

var socket = null;
function init(){
    socket = new WebSocket("wss://localhost:8080/Teste-1/task");    
    socket.onmessage = onMessage;
    
}

function onMessage(event){
     var task = JSON.parse(event.data);
     if(task.action === "add"){
         document.getElementById("point").innerHTML += event.data;
     }                
}

function teste() {
    var action = {
        action: "add",
        name: "Test",
        description: "This is just a test"
    };
    socket.send(JSON.stringify(action));
}
window.onload = init;

HTML 代码

&lt;html&gt;
    &lt;head&gt;
        &lt;title&gt;Test&lt;/title&gt;
        &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"/&gt;
        
    &lt;/head&gt;
    &lt;body&gt;
        &lt;button onclick="teste()"&gt;Teste&lt;/button&gt;
        &lt;div id="point"&gt;&lt;/div&gt;
        &lt;script src="websocket.js"&gt;&lt;/script&gt;
    &lt;/body&gt;
&lt;/html&gt;

Java 代码

public class Task implements Serializable{
    private static final long serialVersionUID = 1L;
    private String name;
    private String description;
    
    public Task(){}

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
 }
@ServerEndpoint(value="/task")
public class TaskSocket {
@Inject
private TaskSessionHandler handler;
@OnOpen
public void open(Session session){
handler.addSession(session);
}
@OnClose
public void close(Session session){
handler.removeSession(session);
}
@OnError
public void onError(Throwable error){
Logger.getLogger(TaskSocket.class.getName()).log(Level.SEVERE, null, error);
}
@OnMessage
public void handleMessage(String message, Session session) {
try (JsonReader reader = Json.createReader(new StringReader(message))) {
JsonObject jsonMessage = reader.readObject();
if ("add".equals(jsonMessage.getString("action"))) {
Task task = new Task();
task.setName(jsonMessage.getString("name"));
task.setDescription(jsonMessage.getString("description"));
handler.addTask(task);
}
}
}
}
@ApplicationScoped
public class TaskSessionHandler {
//Each client connected to the application has its own session.
private final Set<Session> sessions = new HashSet<>();
private final Set<Task> tasks = new HashSet<>();
public void addSession(Session session) {
sessions.add(session);
for(Task task : tasks){
JsonObject addMessage = createJSON(task);
sendToSession(session, addMessage);
}
}
public void removeSession(Session session) {
sessions.remove(session);
}
public List<Task> getTasks(){
List<Task> list = new ArrayList<Task>(tasks);
return list;
}
public void addTask(Task e){
tasks.add(e);
JsonObject message = this.createJSON(e);
sendToAllConnectedSessions(message);
}
private JsonObject createJSON(Task task){
JsonProvider provider = JsonProvider.provider();
JsonObject message = provider.createObjectBuilder()
.add("action", "add")
.add("name",task.getName())
.add("description",task.getDescription()).build();
return message;
}
private void sendToAllConnectedSessions(JsonObject message) {
for (Session session : sessions) {
sendToSession(session, message);
}
}
private void sendToSession(Session session, JsonObject message) {
try {
session.getBasicRemote().sendText(message.toString());
} catch (IOException ex) {
sessions.remove(session);
Logger.getLogger(TaskSessionHandler.class.getName()).log(Level.SEVERE, null, ex);
}
}
}```
<details>
<summary>英文:</summary>
I&#39;m trying to make a web socket connection between js and java, but I get this answer: &lt;br/&gt;
*Uncaught DOMException: An attempt was made to use an object that is not, or is no longer, usable*&lt;br/&gt;
I did it based in some samples on internet. Someone have some idea what can it be?&lt;br/&gt;
Project Name is Teste-1 
&lt;br/&gt;JS Code
var socket = null;
function init(){
socket = new WebSocket(&quot;wss://localhost:8080/Teste-1/task&quot;);    
socket.onmessage = onMessage;
}
function onMessage(event){
var task = JSON.parse(event.data);
if(task.action === &quot;add&quot;){
document.getElementById(&quot;point&quot;).innerHTML += event.data;
}                
}
function teste() {
var action = {
action: &quot;add&quot;,
name: &quot;Test&quot;,
description: &quot;This is just a test&quot;
};
socket.send(JSON.stringify(action));
}
window.onload = init;
HTML Code
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Test&lt;/title&gt;
&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;/&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;button onclick=&quot;teste()&quot;&gt;Teste&lt;/button&gt;
&lt;div id=&quot;point&quot;&gt;&lt;/div&gt;
&lt;script src=&quot;websocket.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
JAVA Codes
public class Task implements Serializable{
private static final long serialVersionUID = 1L;
private String name;
private String description;
public Task(){}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
```ApplicationScoped
@ServerEndpoint(value=&quot;/task&quot;)
public class TaskSocket {
@Inject
private TaskSessionHandler handler;
@OnOpen
public void open(Session session){
handler.addSession(session);
}
@OnClose
public void close(Session session){
handler.removeSession(session);
}
@OnError
public void onError(Throwable error){
Logger.getLogger(TaskSocket.class.getName()).log(Level.SEVERE, null, error);
}
@OnMessage
public void handleMessage(String message, Session session) {
try (JsonReader reader = Json.createReader(new StringReader(message))) {
JsonObject jsonMessage = reader.readObject();
if (&quot;add&quot;.equals(jsonMessage.getString(&quot;action&quot;))) {
Task task = new Task();
task.setName(jsonMessage.getString(&quot;name&quot;));
task.setDescription(jsonMessage.getString(&quot;description&quot;));
handler.addTask(task);
}
}
}
}
@ApplicationScoped
public class TaskSessionHandler {
//Each client connected to the application has its own session.
private final Set&lt;Session&gt; sessions = new HashSet&lt;&gt;();
private final Set&lt;Task&gt; tasks = new HashSet&lt;&gt;();
public void addSession(Session session) {
sessions.add(session);
for(Task task : tasks){
JsonObject addMessage = createJSON(task);
sendToSession(session, addMessage);
}
}
public void removeSession(Session session) {
sessions.remove(session);
}
public List&lt;Task&gt; getTasks(){
List&lt;Task&gt; list = new ArrayList&lt;Task&gt;(tasks);
return list;
}
public void addTask(Task e){
tasks.add(e);
JsonObject message = this.createJSON(e);
sendToAllConnectedSessions(message);
}
private JsonObject createJSON(Task task){
JsonProvider provider = JsonProvider.provider();
JsonObject message = provider.createObjectBuilder()
.add(&quot;action&quot;, &quot;add&quot;)
.add(&quot;name&quot;,task.getName())
.add(&quot;description&quot;,task.getDescription()).build();
return message;
}
private void sendToAllConnectedSessions(JsonObject message) {
for (Session session : sessions) {
sendToSession(session, message);
}
}
private void sendToSession(Session session, JsonObject message) {
try {
session.getBasicRemote().sendText(message.toString());
} catch (IOException ex) {
sessions.remove(session);
Logger.getLogger(TaskSessionHandler.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
</details>
# 答案1
**得分**: 9
我因为在建立和打开 WebSocket 服务器连接之前执行了 websocket.send() 导致了相同的错误消息。
我的建议是**确保只有在连接打开后才发送消息**,这样服务器才能真正接收到这些消息。
我无法确定问题是否与此相关,但我曾经遇到过非常类似的问题,最终找到了解决方法,想要分享一下我的经验。
在我的情况下,**不起作用的代码**如下:
```javascript
const exampleSocket = new WebSocket('wws://example')
exampleSocket.onopen = function (event) {
console.log('连接已打开!')
}
exampleSocket.send(JSON.stringify(msg))
exampleSocket.onmessage = function (event) {
console.log('消息事件数据如下:', event.data)
}

有效的做法是将发送消息的代码移动到 onopen 回调函数中。

const exampleSocket = new WebSocket('wws://example')
    
exampleSocket.onopen = function (event) {
  console.log('连接已打开!')
  exampleSocket.send(JSON.stringify(msg))             // <- 这是变更的部分
}

exampleSocket.onmessage = function (event) {
  console.log('消息事件数据如下:', event.data)
}

附注:在处理确保服务器准备好接收消息时,websocket 的 readyState 属性可能会很有用。

如果值为 1,则表示连接已打开,可以像这样使用:

if (exampleSocket.readyState === 1) {
     console.log("现在可以安全地发送消息了")
}
英文:

I got the same error message due to the websocket.send() being executed before the connection to the webSocket server was established and open.

My contribution would be the advice to make sure messages aren't sent until the connection is open, so that the server actually can receive them.

I cannot tell whether that was the problem in the question asked though. However I faced a very similar problem and ended up here, and wanted to share what worked for me.

In my case the code that didn't work looked like this:

const exampleSocket = new WebSocket(&#39;wws://example&#39;)
exampleSocket.onopen = function (event) {
console.log(&#39;connection is open!&#39;)
}
exampleSocket.send(JSON.stringify(msg))
exampleSocket.onmessage = function (event) {
console.log(&#39;message event data looks like this: &#39;, event.data)
}

What worked was moving the code that sent a message into the onopen callback function.

const exampleSocket = new WebSocket(&#39;wws://example&#39;)
exampleSocket.onopen = function (event) {
console.log(&#39;connection is open!&#39;)
exampleSocket.send(JSON.stringify(msg))             // &lt;- this is the change
}
exampleSocket.onmessage = function (event) {
console.log(&#39;message event data looks like this: &#39;, event.data)
}

Sidenote: the readyState property of websocket could be useful when dealing with making sure the server is ready to receive messages.

If it is 1, it means connection is open, so it could be used like this:

if (exampleSocket.readyState  === 1) {
console.log(&quot;It is safe to send messages now&quot;)
}

huangapple
  • 本文由 发表于 2020年10月23日 02:17:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/64488266.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定