@ckb-ccc/core
Version:
Core of CCC - CKBer's Codebase
95 lines (94 loc) • 3.56 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TransportWebSocket = void 0;
const isomorphic_ws_1 = __importDefault(require("isomorphic-ws"));
class TransportWebSocket {
constructor(url, timeout = 30000) {
this.url = url;
this.timeout = timeout;
this.ongoing = new Map();
}
request(data) {
const socket = (() => {
if (this.socket &&
this.socket.readyState !== this.socket.CLOSING &&
this.socket.readyState !== this.socket.CLOSED &&
this.openSocket) {
return this.openSocket;
}
const socket = new isomorphic_ws_1.default(this.url);
const onMessage = ({ data }) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const res = JSON.parse(data);
if (typeof res !== "object" ||
res === null ||
typeof res.id !== "number") {
throw new Error(`Unknown response ${data}`);
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const id = res.id;
const req = this.ongoing.get(id);
if (!req) {
return;
}
const [resolve, _, timeout] = req;
clearTimeout(timeout);
this.ongoing.delete(id);
resolve(res);
};
const onClose = () => {
this.ongoing.forEach(([_, reject, timeout]) => {
clearTimeout(timeout);
reject(new Error("Connection closed"));
});
this.ongoing.clear();
};
socket.onclose = onClose;
socket.onerror = onClose;
socket.onmessage = onMessage;
this.socket = socket;
this.openSocket = new Promise((resolve) => {
if (socket.readyState === socket.OPEN) {
resolve(socket);
}
else {
socket.onopen = () => {
resolve(socket);
};
}
});
return this.openSocket;
})();
return new Promise((resolve, reject) => {
const req = [
resolve,
reject,
setTimeout(() => {
this.ongoing.delete(data.id);
void socket
.then((socket) => socket.close())
.catch((err) => reject(err));
reject(new Error("Request timeout"));
}, this.timeout),
];
this.ongoing.set(data.id, req);
void socket
.then((socket) => {
if (socket.readyState === socket.CLOSED ||
socket.readyState === socket.CLOSING) {
clearTimeout(req[2]);
this.ongoing.delete(data.id);
reject(new Error("Connection closed"));
}
else {
socket.send(JSON.stringify(data));
}
})
.catch((err) => reject(err));
});
}
}
exports.TransportWebSocket = TransportWebSocket;
;