Идиоматический c способ решить эту проблему с помощью LitElement - заставить объект BTLE генерировать события при изменении его состояния, а другие объекты (например, пользовательские элементы), которым важно его состояние, прослушивать эти события.
Самый простой способ сделать это в веб-приложении - сделать класс BTLE расширенным EventTarget , что даст ему addEventListener
, dispatchEvent
и т. Д. c. методы. Затем вместо передачи функций обратного вызова в конструктор BTLE ваш пользовательский элемент будет вызывать addEventListener
, чтобы начать прослушивание. Когда состояние объекта BTLE изменяется, вместо вызова this.callbackFunction(...)
он будет вызывать this.dispatchEvent(new Event('state-change'))
(например).
Чтобы выполнить sh, ваш пользовательский элемент должен будет определить собственный метод получения и установки, так он знает, когда его свойство bluetoothGatt
изменяется, потому что ему нужно будет вызвать addEventListener
на новом BTLE. Это самая сложная часть, поэтому я настоятельно рекомендую прочитать раздел «Настройка средств доступа к свойствам» в документации по LitElement.
В следующем фрагменте вы можете увидеть рабочий пример того, как это может посмотрите на практике:
const { LitElement, html } = litElement;
const BluetoothGattState = { Disconnected: 0, Connected: 1 };
// A simple app to test our custom element
class MyApp extends LitElement {
render() {
// Pass the BTLE object to `<bt-indicator>` as a property
return html`
<bt-indicator .bluetoothGatt=${new BTLE()}></bt-indicator>
`;
}
}
customElements.define('my-app', MyApp);
// Our <bt-indicator> custom element
class BtIndicator extends LitElement {
static get properties() {
return {
bluetoothGatt: { type: Object },
btState: { type: Number },
};
}
constructor() {
super();
this._bluetoothGatt = null;
this._handleBtGattStateChange = this._handleBtGattStateChange.bind(this);
}
render() {
return html`Bluetooth status: ${
this.btState === BluetoothGattState.Connected ? '✅' : '?'
}`;
}
// A custom setter that calls addEventListener whenever the bluetoothGatt
// property changes
set bluetoothGatt(obj) {
const oldObj = this._bluetoothGatt;
if (oldObj) {
// Remove event listener from old BTLE
oldObj.removeEventListener('state-change', this._handleBtGattStateChange);
}
if (obj) {
this._bluetoothGatt = obj;
this.btState = obj.state;
// Add event listener to new BTLE
obj.addEventListener('state-change', this._handleBtGattStateChange);
} else {
this._bluetoothGatt = null;
}
// Tell LitElement the property changed so it can re-render
this.requestUpdate('bluetoothGatt', oldObj);
}
get bluetoothGatt() {
return this._bluetoothGatt;
}
_handleBtGattStateChange(evt) {
// update this.btState when the BTLE's stage changes
this.btState = evt.target.state;
}
}
customElements.define('bt-indicator', BtIndicator);
// BTLE as a simple EventTarget -- connects/disconnects every 1000ms and
// dispatches 'state-change'
class BTLE extends EventTarget {
constructor() {
super();
this.setState(BluetoothGattState.Disconnected);
setInterval(() => {
this.setState(this.state === BluetoothGattState.Disconnected ? BluetoothGattState.Connected : BluetoothGattState.Disconnected);
}, 1000);
}
setState(val) {
this.state = val;
this.dispatchEvent(new Event('state-change'));
}
}
<script src="https://bundle.run/lit-element@2.2.1"></script>
<my-app><my-app>