2

I have the following code, to scan for a Bluetooth device, which for every device found, I want to add the device to an array.

devices: Observable<Array<string>>;

bluetoothAdd() {
    this.isScanning = true;
    var plusIcon = this.page.getViewById("add");
    plusIcon.style.opacity = 0;

    var self = this; 
    bluetooth.hasCoarseLocationPermission().then(
        function (granted) {
            if (!granted) {
                bluetooth.requestCoarseLocationPermission();
            } else {
                bluetooth.startScanning({
                    serviceUUIDs: ["133d"],
                    seconds: 4,
                    onDiscovered: function (peripheral) {
                        console.log("Periperhal found with UUID: " + peripheral.UUID);
                        this.devices.push(peripheral); // <- Problem Line
                    }
                }).then(function () {
                    console.log("scanning complete");
                    self.isScanning = false;
                    plusIcon.style.opacity = 1;
                }, function (err) {
                    console.log("error while scanning: " + err);
                });
                this.isScanning = false;
            }
        });
}

However, this code throws the following error:

JavaScript error: file:///app/Pages/Home/home.component.js:99:37: JS ERROR TypeError: undefined is not an object (evaluating 'this.devices.push')

I am working in Typescript, but I know the push function is a JS thing. Not sure how I would do this in Typescript - what have I done wrong?

Whit Waldo
  • 3,312
  • 3
  • 36
  • 60
George Edwards
  • 8,017
  • 16
  • 64
  • 135
  • 1
    This has nothing to do with TypeScript. `this` is not what you expect. See http://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work. You can use `self` though – elclanrs Apr 16 '16 at 17:01

2 Answers2

3

It has nothing to do with TypeScript, it's just normal Javascript rules for this.

The problem this points to the function you give to onDiscovered instead of the class.

You can fix it by using the self variable you have defined or by rewriting the code to use arrow functions instead, like this:

devices: Observable<Array<string>>;

bluetoothAdd() {
    this.isScanning = true;
    var plusIcon = this.page.getViewById("add");
    plusIcon.style.opacity = 0;


    bluetooth.hasCoarseLocationPermission().then(
        (granted) => {
            if (!granted) {
                bluetooth.requestCoarseLocationPermission();
            } else {
                bluetooth.startScanning({
                    serviceUUIDs: ["133d"],
                    seconds: 4,
                    onDiscovered: (peripheral) => {
                        console.log("Periperhal found with UUID: " + peripheral.UUID);
                        this.devices.push(peripheral); // <- Problem Line
                    }
                }).then(() => {
                    console.log("scanning complete");
                    this.isScanning = false;
                    plusIcon.style.opacity = 1;
                }, (err) => {
                    console.log("error while scanning: " + err);
                });
                this.isScanning = false;
            }
        });
}

Also, as Bhabishya pointed out the type of devices is Observable. That type has no push method defined on it. Instead it will be able to emit an array of Devices.

If all you need is an array you should also change the devices to be an array of string, instead of an Observable of array of string.

devices: Array<string>;

You will also have to initialize it.

devices: Array<string> = [];
toskv
  • 26,120
  • 7
  • 64
  • 66
  • Are you sure about the `this` problem ? In his **onDiscovered** function, `this` should refers to the class, because he his using **arows**, and unlike functions, arrows **share** the same lexical `this` as their surrounding code. There is no new context. – Paul Boutes Apr 16 '16 at 17:14
  • @PaulBoutes there are no arrow functions in the original post. Adding them is the fix. – toskv Apr 16 '16 at 17:16
  • 1
    My bad, I didn't see ! – Paul Boutes Apr 16 '16 at 17:18
  • As you note, that code produces the error "property 'push' does not exist on object observable...", so how do I achieve the result I am after? i.e. add each new device that is found to the array? – George Edwards Apr 16 '16 at 19:36
  • Just make it a simple array as suggested in the other answe. I'll update my answer. – toskv Apr 16 '16 at 19:38
  • I still get this error with your updated code `JavaScript error: file:///app/Pages/Home/home.component.js:98:38: JS ERROR TypeError: undefined is not an object (evaluating '_this.devices.push')`? – George Edwards Apr 17 '16 at 13:18
  • well.. that might be because the devices array is not initialized? – toskv Apr 17 '16 at 13:19
2

You have defined devices as Observable of array devices: Observable<Array<string>> and not an array devices: Array<string> on which you can call the push() function.

George Edwards
  • 8,017
  • 16
  • 64
  • 135
Bhabishya Kumar
  • 721
  • 3
  • 7