【问题标题】:Handling asynchronous JavaScript Chrome Console Errors处理异步 JavaScript Chrome 控制台错误
【发布时间】:2017-05-04 20:49:14
【问题描述】:

我在 Chrome 扩展中有一些 Javascript,每 3 秒运行一次,并尝试连接到本地 WebSocket 服务器。

setInterval(attemptConnection, 3000);

function attemptConnection() {

try {
    var exampleSocket = new WebSocket("ws://localhost:8080");
    exampleSocket.onmessage = function (event) {
        var JsonObject = JSON.parse(event.data);
        document.getElementById(JsonObject.elementTagValue).setAttribute("value", JsonObject.valueToSet);

    }
}

catch(err) {
//do something here
    }

我只希望在特定时间点运行本地 WebSocket 服务器。如果建立连接,WebSocket 服务器将发送一些 javascript 将立即使用的 JSON 数据。

当我进入开发人员工具时,我看到我在控制台中多次收到 ERR_CONNECTION_REFUSED,因为在该端点显然没有任何内容,这是预期的行为。有没有办法抑制这些控制台输出或更好地处理这个问题?

编辑 - 更新了代码,我仍然得到错误输出到控制台

setInterval(attemptConnection, 3000);

function attemptConnection() {
    var exampleSocket = new WebSocket("ws://localhost:8080");
    exampleSocket.onmessage = function (event) {
        var JsonObject = JSON.parse(event.data);
        document.getElementById(JsonObject.elementTagValue).setAttribute("value", JsonObject.valueToSet);
        exampleSocket.send(event.data);

        exampleSocket.onerror = function () {
            //do nothing
        }
    }
}

【问题讨论】:

  • 如果你使用exampleSocket.onerror也许可以?
  • try/catch 不起作用,因为错误是异步发生的。
  • 网络错误总是被记录到控制台,无论它们是否在 JS 中处理。不过,您可以通过 devtools 设置隐藏它们
  • 是否存在大量错误淹没控制台的风险?如果我长时间打开浏览器,我希望不会导致 Chrome 崩溃。
  • 半生不熟的想法:有没有办法在调用new WebSocket('...')之前检查连接是否成功?我还没有研究过。

标签: javascript google-chrome-extension websocket


【解决方案1】:

假设您必须处理onerror 的错误,您也应该处理onclose。 最简单的检查是错误代码1000,这意味着正常的套接字关闭

exampleSocket.onclose = (event) => {
   if (event.code != 1000) {
      // "Normal closure, meaning that the purpose for which the connection was established has been fulfilled.";
   }
}

虽然描述了对错误代码的完整处理here,但为了您的方便,我将其放在这里:

     exampleSocket.onclose = (event) => {
        if (event.code == 1000)
            reason = "Normal closure, meaning that the purpose for which the connection was established has been fulfilled.";
        else if(event.code == 1001)
            reason = "An endpoint is \"going away\", such as a server going down or a browser having navigated away from a page.";
        else if(event.code == 1002)
            reason = "An endpoint is terminating the connection due to a protocol error";
        else if(event.code == 1003)
            reason = "An endpoint is terminating the connection because it has received a type of data it cannot accept (e.g., an endpoint that understands only text data MAY send this if it receives a binary message).";
        else if(event.code == 1004)
            reason = "Reserved. The specific meaning might be defined in the future.";
        else if(event.code == 1005)
            reason = "No status code was actually present.";
        else if(event.code == 1006)
           reason = "The connection was closed abnormally, e.g., without sending or receiving a Close control frame";
        else if(event.code == 1007)
            reason = "An endpoint is terminating the connection because it has received data within a message that was not consistent with the type of the message (e.g., non-UTF-8 [http://tools.ietf.org/html/rfc3629] data within a text message).";
        else if(event.code == 1008)
            reason = "An endpoint is terminating the connection because it has received a message that \"violates its policy\". This reason is given either if there is no other sutible reason, or if there is a need to hide specific details about the policy.";
        else if(event.code == 1009)
           reason = "An endpoint is terminating the connection because it has received a message that is too big for it to process.";
        else if(event.code == 1010) // Note that this status code is not used by the server, because it can fail the WebSocket handshake instead.
            reason = "An endpoint (client) is terminating the connection because it has expected the server to negotiate one or more extension, but the server didn't return them in the response message of the WebSocket handshake. <br /> Specifically, the extensions that are needed are: " + event.reason;
        else if(event.code == 1011)
            reason = "A server is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request.";
        else if(event.code == 1015)
            reason = "The connection was closed due to a failure to perform a TLS handshake (e.g., the server certificate can't be verified).";
        else
            reason = "Unknown reason";
     }

var exampleSocket = new WebSocket("ws://localhost:8080");
    exampleSocket.onmessage = function (event) {
        var JsonObject = JSON.parse(event.data);
        console.log(JsonObject)
        exampleSocket.send(event.data);

        exampleSocket.onerror = function () {
            //do nothing
        }
    }
exampleSocket.onclose = (event) => {
            if (event.code == 1000)
                reason = "Normal closure, meaning that the purpose for which the connection was established has been fulfilled.";
            else if(event.code == 1001)
                reason = "An endpoint is \"going away\", such as a server going down or a browser having navigated away from a page.";
            else if(event.code == 1002)
                reason = "An endpoint is terminating the connection due to a protocol error";
            else if(event.code == 1003)
                reason = "An endpoint is terminating the connection because it has received a type of data it cannot accept (e.g., an endpoint that understands only text data MAY send this if it receives a binary message).";
            else if(event.code == 1004)
                reason = "Reserved. The specific meaning might be defined in the future.";
            else if(event.code == 1005)
                reason = "No status code was actually present.";
            else if(event.code == 1006)
               reason = "The connection was closed abnormally, e.g., without sending or receiving a Close control frame";
            else if(event.code == 1007)
                reason = "An endpoint is terminating the connection because it has received data within a message that was not consistent with the type of the message (e.g., non-UTF-8 [http://tools.ietf.org/html/rfc3629] data within a text message).";
            else if(event.code == 1008)
                reason = "An endpoint is terminating the connection because it has received a message that \"violates its policy\". This reason is given either if there is no other sutible reason, or if there is a need to hide specific details about the policy.";
            else if(event.code == 1009)
               reason = "An endpoint is terminating the connection because it has received a message that is too big for it to process.";
            else if(event.code == 1010) // Note that this status code is not used by the server, because it can fail the WebSocket handshake instead.
                reason = "An endpoint (client) is terminating the connection because it has expected the server to negotiate one or more extension, but the server didn't return them in the response message of the WebSocket handshake. <br /> Specifically, the extensions that are needed are: " + event.reason;
            else if(event.code == 1011)
                reason = "A server is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request.";
            else if(event.code == 1015)
                reason = "The connection was closed due to a failure to perform a TLS handshake (e.g., the server certificate can't be verified).";
            else
                reason = "Unknown reason";
                console.error(reason);
         }

我在这里添加了一个完整的 WebSocket 客户端包装器,它也通过简单的重新连接逻辑(从 WebSocket 节点官方示例移植)通过 autoReconnectIntervalmaxAttempts 处理重新连接。

function WebSocketClient() {
  this.number = 0; // Message number
  this.autoReconnectInterval = 5 * 1000; // ms
  this.maxAttempts = 3;
  this.attempts = 0;
}
WebSocketClient.prototype.open = function(url) {
  var self = this;
  this.url = url;

  this.instance = new WebSocket(this.url);
  this.instance.onopen = () => {
    self.onopen();
  }
  this.instance.onmessage = (data, flags) => {
    self.number++;
    self.onmessage(data, flags, this.number);
  }
  this.instance.onclose = (e) => {
    switch (e) {
      case 1000: // CLOSE_NORMAL
        console.log("WebSocket: closed normally");
        break;
      default: // Abnormal closure
        if (self.attempts < self.maxAttempts) self.reconnect(e);
        self.attempts++;
        break;
    }
    this.onclose(e);
  }
  this.instance.onerror = (e) => {
    switch (e.code) {
      case 'ECONNREFUSED':
        self.reconnect(e);
        break;
      default:
        self.onerror(e);
        break;
    }
  }
}
WebSocketClient.prototype.send = function(data, option) {
  try {
    this.instance.send(data, option);
  } catch (e) {
    this.instance.emit('error', e);
  }
}
WebSocketClient.prototype.reconnect = function(e) {
  var self = this;

  console.log("WebSocketClient: retry in %s ms attempt %d", self.autoReconnectInterval, self.attempts);
  setTimeout(function() {
    console.log("WebSocketClient: reconnecting...");
    self.open(self.url);
  }, self.autoReconnectInterval);
}
WebSocketClient.prototype.onopen = function(e) {
  console.log("WebSocketClient: open", arguments);
}
WebSocketClient.prototype.onmessage = function(data, flags, number) {
  console.log("WebSocketClient: message", data);
}
WebSocketClient.prototype.onerror = function(e) {
  console.log("WebSocketClient: error");
}
WebSocketClient.prototype.onclose = function(e) {
  console.log("WebSocketClient: closed");
}

var wsc = new WebSocketClient();
wsc.open('wss://localhost:8080/');
wsc.onopen = function(e) {
  console.log("WebSocketClient connected:", e);
  this.send("echo");
}
wsc.onmessage = function(data, flags, number) {
  console.log("WebSocketClient message", data);
}

【讨论】:

  • 谢谢。我试过了,但我仍然向控制台输出错误。我认为套接字从未打开过,尝试连接时发生错误。
  • 我已经添加了一个代码sn-p,在你的客户端运行它并告诉我哪个是错误代码。
  • 控制台输出“连接异常关闭,例如,没有发送或接收关闭控制帧”和“ERR_CONNECTION_REFUSED”
  • 好的,它是错误代码1006。这意味着尚未发送控制帧(关闭、Ping 或 Pong)。你的 WebSocket 客户端代码是不是都在上面的 sn-p 中? WebSocker 服务器正在为异常的客户端执行发送此特殊代码。
  • 接受您的回答,因为它对其他人来说是最全面的。
【解决方案2】:

您不能使用try/catch 来捕获此错误,因为它是异步发生的。您应该使用onerror 事件处理程序。

function attemptConnection() {
    var exampleSocket = new WebSocket("ws://localhost:8080");
    exampleSocket.onmessage = function (event) {
        var JsonObject = JSON.parse(event.data);
        document.getElementById(JsonObject.elementTagValue).setAttribute("value", JsonObject.valueToSet);

    };
    exampleSocket.onerror = function() {
        // do nothing
    };
}

【讨论】:

  • 谢谢,我应该意识到这一点。但是,我仍然在控制台中生成错误。
  • 可能无法抑制它们。
【解决方案3】:

如果您在错误处理程序中清除超时,您可能只能记录 1 个错误。您还可以在 onmessage 函数中启动另一个 Timeout,这样它只会在收到消息时运行。试试看

var timer = null;

function attemptConnection() {
    var exampleSocket = new WebSocket("ws://localhost:8080");

        exampleSocket.onmessage = function (event) {
        timer = setTimeout(attemptConnection, 100);
        var JsonObject = JSON.parse(event.data);
        document.getElementById(JsonObject.elementTagValue).setAttribute("value", JsonObject.valueToSet);
        exampleSocket.send(event.data);
    }
    exampleSocket.onerror = function (event) {
          console.log('error')
            //do nothin
          clearTimeout(timer)

      }
}

attemptConnection();

【讨论】:

  • 问题是浏览时我不知道套接字服务器什么时候可用,所以我不断地轮询它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-12-13
  • 2016-05-14
  • 1970-01-01
  • 1970-01-01
  • 2017-07-29
  • 2012-05-25
  • 1970-01-01
相关资源
最近更新 更多