Контекст: Я использую 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);
}
}
}