@bitrix24/b24jssdk
Version:
Bitrix24 REST API JavaScript SDK
194 lines (191 loc) • 5.38 kB
JavaScript
/**
* @package @bitrix24/b24jssdk
* @version 2.2.0
* @copyright (c) 2026 Bitrix24
* @license MIT
* @see https://github.com/bitrix24/b24jssdk
* @see https://bitrix24.github.io/b24jssdk/
*/
import { Type } from '../tools/type.mjs';
import { Text } from '../tools/text.mjs';
import { AbstractConnector } from './abstract-connector.mjs';
import { ConnectionType } from '../types/pull.mjs';
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
const LONG_POLLING_TIMEOUT = 60;
class LongPollingConnector extends AbstractConnector {
static {
__name(this, "LongPollingConnector");
}
_active;
_requestTimeout;
_failureTimeout;
// Created lazily on the first connect() rather than in the constructor: the
// connector is built eagerly by PullClient.init() (which runs inside start())
// regardless of the chosen transport, and `new XMLHttpRequest()` throws a
// ReferenceError under SSR/Node where the global is absent. Deferring it keeps
// construct + init + start SSR-safe; connect() degrades gracefully instead. (#222)
_xhr;
_requestAborted;
constructor(config) {
super(config);
this._active = false;
this._connectionType = ConnectionType.LongPolling;
this._requestTimeout = null;
this._failureTimeout = null;
this._xhr = null;
this._requestAborted = false;
}
/**
* @inheritDoc
*/
connect() {
if (!this._xhr) {
if (typeof XMLHttpRequest === "undefined") {
this._callbacks.onError(
new Error(
"LongPollingConnector: XMLHttpRequest is not available in this environment (SSR/Node); a long-polling connection requires a browser"
)
);
return;
}
this._xhr = this.createXhr();
}
this._active = true;
this.performRequest();
}
/**
* @inheritDoc
* @param code
* @param reason
*/
disconnect(code, reason) {
this._active = false;
this.clearTimeOut();
if (this._xhr) {
this._requestAborted = true;
this._xhr.abort();
}
this._disconnectCode = code;
this._disconnectReason = reason;
this.connected = false;
}
performRequest() {
if (!this._active) {
return;
}
if (!this.connectionPath) {
throw new Error("Long polling connection path is not defined");
}
const xhr = this._xhr;
if (!xhr) {
return;
}
if (xhr.readyState !== 0 && xhr.readyState !== 4) {
return;
}
this.clearTimeOut();
this._failureTimeout = setTimeout(() => {
this.connected = true;
}, 5e3);
this._requestTimeout = setTimeout(
this.onRequestTimeout.bind(this),
LONG_POLLING_TIMEOUT * 1e3
);
xhr.open("GET", this.connectionPath);
xhr.send();
}
onRequestTimeout() {
this._requestAborted = true;
this._xhr?.abort();
this.performRequest();
}
onXhrReadyStateChange() {
const xhr = this._xhr;
if (!xhr) {
return;
}
if (xhr.readyState === 4) {
if (!this._requestAborted || xhr.status == 200) {
this.onResponse(xhr.response);
}
this._requestAborted = false;
}
}
/**
* Via http request
* @inheritDoc
*/
send(buffer) {
const path = this._parent.getPublicationPath();
if (!path) {
this.getLogger().error(`${Text.getDateForLog()}: Pull: publication path is empty`).catch(() => {
});
return false;
}
if (typeof XMLHttpRequest === "undefined") {
this.getLogger().error(
`${Text.getDateForLog()}: Pull: XMLHttpRequest is not available; cannot publish`
).catch(() => {
});
return false;
}
const xhr = new XMLHttpRequest();
xhr.open("POST", path);
xhr.send(buffer);
return true;
}
onResponse(response) {
this.clearTimeOut();
const xhr = this._xhr;
if (!xhr) {
return;
}
if (xhr.status === 200) {
this.connected = true;
if (Type.isStringFilled(response) || response instanceof ArrayBuffer) {
this._callbacks.onMessage(response);
} else {
this._parent.session.mid = null;
}
this.performRequest();
} else if (xhr.status === 304) {
this.connected = true;
if (xhr.getResponseHeader("Expires") === "Thu, 01 Jan 1973 11:11:01 GMT") {
const lastMessageId = xhr.getResponseHeader("Last-Message-Id");
if (Type.isStringFilled(lastMessageId)) {
this._parent.setLastMessageId(lastMessageId || "");
}
}
this.performRequest();
} else {
this._callbacks.onError(new Error("Could not connect to the server"));
this.connected = false;
}
}
// region Tools ////
clearTimeOut() {
if (this._failureTimeout) {
clearTimeout(this._failureTimeout);
this._failureTimeout = null;
}
if (this._requestTimeout) {
clearTimeout(this._requestTimeout);
this._requestTimeout = null;
}
}
createXhr() {
const result = new XMLHttpRequest();
if (this._parent.isProtobufSupported() && !this._parent.isJsonRpc()) {
result.responseType = "arraybuffer";
}
result.addEventListener(
"readystatechange",
this.onXhrReadyStateChange.bind(this)
);
return result;
}
// endregion ////
}
export { LongPollingConnector };
//# sourceMappingURL=long-polling-connector.mjs.map