简体   繁体   中英

Async setter / getter in JavaScript

I'm working with Web Bluetooth which requires a lot of async operations. I've implemented setters and getters for properties such as the device name. Async setters and getters are not supported by default in ES6, so I've used the following workaround as advised here :

get name() {
  return ( async () => {
    try {
      const data = await this._readData(this.nameCharacteristic);
      const decoder = new TextDecoder("utf-8");
      const name = decoder.decode(data);
      return name;
    } 
    catch (error) {
      return error;
    }
  })();
}

And:

set name(name) {
  return ( async (name) => {
    const byteArray = new Uint8Array(name.length);
    for (let i = 0; i < name.length; i += 1) {
      byteArray[i] = name.charCodeAt(i);
    }
    return await this._writeData(this.nameCharacteristic, byteArray);
  })(name);
}

I can do the following succesfully with the getter:

await device.connect();
await device.name;
await device.<some async BLE operation>

But the following with the setter results in the reference error "Uncaught ReferenceError: Invalid left-hand side in assignment" for the setter:

await device.connect();
await device.name = "newName";
await device.<some async BLE operation>

If I remove the await keyword, the error is fixed, but the script will fail because it will attempt two GATT operations at the same time, which is not supported.

So it seems that I can only await a getter and not a setter. Is there something wrong with my implementation of the getter that causes this? Do I have to go back to using a function like device.nameSet() instead of setter when doing async operations?

For the record, _writeData() and _readData() look like this:

async _writeData(characteristic, dataArray) {
  if (!this.bleIsBusy) {
    try {
      this.bleIsBusy = true;
      await characteristic.writeValue(dataArray);
      this.bleIsBusy = false;
    }
    catch (error) {
      return error;
    }
    return Promise.resolve();
  }
  else {
    return Promise.reject(new Error("GATT operation already pending"));
  }
}

async _readData(characteristic) {
  if (!this.bleIsBusy) {
    try {
      this.bleIsBusy = true;
      const dataArray = await characteristic.readValue();
      this.bleIsBusy = false;

      return dataArray;
    }
    catch (error) {
      return error;
    }
  }
  else {
    return Promise.reject(new Error("GATT operation already pending"));
  }
}

Maybe try setting the value returned from await this._writeData(this.nameCharacteristic, byteArray); ...

set name(name) {
  return ( async (name) => {
    const byteArray = new Uint8Array(name.length);
    for (let i = 0; i < name.length; i += 1) {
      byteArray[i] = name.charCodeAt(i);
    }
    const result = await this._writeData(this.nameCharacteristic, byteArray);
    return result;
  })(name);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM