2016-11-01 4 views
0

Контекст: Я использую websocket для подключения к сетевому серверу для своего сайта. У меня есть пользовательские методы, и способ обработки сообщений также является обычным явлением.Как отменить обнаружение изменений для метода especifc для WebSocket?

Если сообщение, которое я хочу отправить, слишком велико, я разберу его на множество небольших сообщений, чтобы один сокет мог отправлять «параллельные» сообщения. Эта часть работает отлично

Проблемы: Каждый раз, когда «часть сообщения» достигает WebSocket, он переходит в «MessageDecoder», чтобы быть декодируются и каскадным в реальное сообщение, то (я предполагаю) zones.js спусковых обнаружение изменения ширины страницы. Так как это происходит так же быстро, как websocket может обрабатывать части сообщения, это замедляет все приложение до обхода, что еще хуже, ничто в приложении никогда не изменяется до тех пор, пока не будет завершено все сообщение, и THEN вызовет обратные вызовы (которые являются теми, которые вызывают перемены). Скачивание файла обычно приводит к 6000 частям сообщения, где только последний может когда-либо надеяться внести какие-либо изменения в приложение.

Я уже пытался вслепую добавить 'this.zone.runOutsideAngular (() => {' к коду, но я не смог его исправить. Я не совсем понимаю, где это применимо для использования, поскольку Я не совсем понимаю, когда zone.js решает запустить обнаружение изменений. В приведенном ниже коде будет комментарий, который указывает ТОЛЬКО фрагмент кода, который должен ВСЕГДА запускать обнаружение изменений.

OBS: Я мог бы захотите позже добавить сообщение с идентификатором zzz, полученным с помощью xxx счетчика yyy parts (чтобы сделать панель загрузки), чтобы также потребовалось вызвать обнаружение изменений. Но, надеюсь, можно гарантировать, что только те, кто слушает этот метод/переменная будет проверять изменения, а не всю страницу

Код:

import { Injectable, NgZone } from '@angular/core'; 

declare var MessageDecoder: any; 
declare var MessageEncoder: any; 
declare var GetMessageTranslator: any; 
declare var TextDecoder: any; 
declare var DataStream: any; 
declare var StatusCheck: any; 
@Injectable() 
export class ConnectionService { 
    public connection: any; 
    private status: boolean; 
    public ping: number; 
    public errorState: number; 
    public interval: number; 

    constructor(private zone: NgZone) { 
     this.startAutoConnect(); 
    } 

    public getState() { 
     if (this.connection == undefined) { 
      return "offline"; 
     } 
     if (this.errorState > new Date().getTime()) { 
      return "error"; 
     } 
     if (this.connection.readyState != WebSocket.OPEN) { 
      return "offline"; 
     } else { 
      if (this.status) { 
       return "loggedIn"; 
      } else { 
       return "connected"; 
      } 
     } 
    } 
    autoConnectHandle: any; 
    waitForSocketConnection(socket, callback) { 
     setTimeout(
      function() { 
       if (socket.readyState === 1) { 
        if (callback !== undefined) { 
         callback(); 
        } 
        return; 
       } else { 
        this.waitForSocketConnection(socket, callback); 
       } 
      }, 5); 
    }; 
    onOpen1 = function() { 
     this.aThis.onOpen(this.aThis); 
    } 
    onOpen = function() { 
     this.waitForSocketConnection(this.connection,() => { 
      clearInterval(this.autoConnectHandle); 
      this.autoConnectHandle = undefined; 
      var connection: any = this.connection; 
      var aThis: ConnectionService = this; 
      connection.onclose = function() { 
       aThis.startAutoConnect(); 
      } 
      connection.supersend = connection.send; 
      connection.send = function(message, callback, type) { 
       if (message.ID == undefined) { 
        message.configure(); 
        message.init(this); 
       } 
       if (this.promiseMap[message.getRequestID()] == undefined) { 
        this.promiseMap[message.getRequestID()] = { 
         type: type, 
         callback: callback, 
         complete: false 
        }; 
       } 
       message.writeToChannel(this); 
      } 
      connection.attr = {}; 
      connection.promiseMap = {}; 

      connection.onerror = function(error) { 
       this.errorState = new Date().getTime() + 1500; 
       console.error('WebSocket Error ' + error); 
      }; 
      connection.channelRead = function(message) {//called by the message decoder after the message is complete 
       console.log("got: " + message.getClass()); 
       var promisse = this.promiseMap[message.getRequestID()]; 
       if (promisse != undefined) { 
        if (promisse.complete) { 
         return; 
        } else { 
         if (promisse.type == message.getClass() || promisse.type == undefined) { 
          if (promisse.callback != undefined) { 
           //THIS SHOULD TRIGGER THE CHANGE DETECTION, ANYTHING ELSE MEANS THAT IT WAS 
           //A MESSAGE THAT DON'T CARE ABOUT THE RESULT, SO NOTHING WILL CHANGE BECAUSE 
           //OF IT 
           promisse.callback(message); 
          } 
          promisse.complete = true; 
          delete this.promiseMap[message.getRequestID()]; 
         } else if (message.getClass() == "NullServerMessage") { 

         } 
        } 
        var answer = message.processAnswer(this); 
        if (answer.getClass() != "NullServerMessage") { 
         console.log("sent: " + answer.getClass()); 
         this.send(answer); 
        } 
       } 
      } 
      connection.decoder = new MessageDecoder(); 
      connection.encoder = new MessageEncoder(); 

      connection.onmessage = (e) => { 
       //I believe this is triggering the excess of change detections 
       var arrayBuffer; 
       var fileReader = <any>new FileReader(); 
       fileReader.onload = function() { 
        connection.decoder.decode(connection, new DataStream(this.result), undefined) 
       }; 
       fileReader.readAsArrayBuffer(e.data); 
      }; 
      aThis.interval = setInterval(() => new function() { 
       connection.pingCounter = new Date().getTime(); 
       connection.send(new StatusCheck(), function(message) { 
        aThis.status = message.status; 
        aThis.ping = new Date().getTime() - connection.pingCounter; 
       }); 
      }, 1000); 
      connection.send(new GetMessageTranslator(), function(message) { 
       connection.decoder.translator = message.map; 
       connection.encoder.translator = message.map; 
       connection.encoder.translator.getKeyByValue = function(value) { 
        for (var prop in this) { 
         if (this.hasOwnProperty(prop)) { 
          if (this[prop] === value) 
           return prop; 
         } 
        } 
       } 

      }); 
     }); 
    } 

    startAutoConnect() { 
     if (this.connection) { 
      this.connection.close(); 
      if (this.interval != undefined) { 
       clearInterval(this.interval); 
       this.interval = undefined; 
      } 
      this.connection = undefined; 
     } 
     var connection: any; 
     var aThis: ConnectionService = this; 
     if (!this.autoConnectHandle) { 
      this.autoConnectHandle = setInterval(() => new function() { 
       if (this.connection == undefined) { 
        aThis.connection = connection = new WebSocket('ws://localhost:80/websocket'); 
        connection.aThis = aThis; 
        connection.onopen = aThis.onOpen1; 
        connection.onerror = function(error) { 
         aThis.startAutoConnect(); 
        }; 
       } 
      }, 1500); 
     } 
    } 

} 

ответ

0

Я думаю, что я получил его, изменив

constructor(private zone: NgZone) { 
    this.startAutoConnect(); 
} 

в

constructor(private zone: NgZone) { 
    this.zone.runOutsideAngular(() => { 
     this.startAutoConnect(); 
    }); 
} 

Это сделано так, что ничего не было обновления в ответ на WebSocket звонки кроме счетчик пинга, и результат из моих сообщений в websocket был обновлен только после обновления счетчика пинга, что заставляет меня думать, что это действительно сработало, сообщения были n от запуска обнаружения изменений, вроде как я хотел.

Проблема заключается в том, что исходная проблема всего, что происходит сверх медленным во время загрузки, сохраняется, поэтому это никогда не было причиной этого.

изменение

    if (promisse.type == message.getClass() || promisse.type == undefined) { 
         if (promisse.callback != undefined) { 
          //THIS SHOULD TRIGGER THE CHANGE DETECTION, ANYTHING ELSE MEANS THAT IT WAS 
          //A MESSAGE THAT DON'T CARE ABOUT THE RESULT, SO NOTHING WILL CHANGE BECAUSE 
          //OF IT 
          promisse.callback(message); 
         } 
         promisse.complete = true; 
         delete this.promiseMap[message.getRequestID()]; 

в

    if (promisse.type == message.getClass() || promisse.type == undefined) { 
         if (promisse.callback != undefined) { 
          this.aThis.zone.run(() => { 
           promisse.callback(message); 
          }); 
         } 
         promisse.complete = true; 
         delete this.promiseMap[message.getRequestID()]; 

сделал обнаружение изменений происходит каждый раз, когда сообщение было полным и обратным вызовом после завершения обработки.

Смежные вопросы