Wednesday, June 5, 2024
 Popular · Latest · Hot · Upcoming
60
rated 0 times [  66] [ 6]  / answers: 1 / hits: 28905  / 8 Years ago, fri, april 15, 2016, 12:00:00

I have a Javascript function (in an Angular 2 NativeScript based mobile app) which is triggered on a button press, it should hide the button and show an activity indicator in its place, carry out a Bluetooth scan, which when completed switches off the activity indicator and shows the original button.



bluetoothAdd() {
this.isScanning = true;
var plusIcon = this.page.getViewById(add);
plusIcon.style.opacity = 0;
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);
}
}).then(function () {
console.log(scanning complete);
this.isScanning = false;
plusIcon.style.opacity = 1;
}, function (err) {
console.log(error while scanning: + err);
});
this.isScanning = false;
}
});
}


Unfortunately, the this.isScanning = false; line throws all of these errors. What have I done wrong?



CONSOLE ERROR file:///app/tns_modules/angular2/src/platform/server/parse5_adapter.js:55:75: EXCEPTION: Error: Uncaught (in promise): TypeError: Attempted to assign to readonly property.
CONSOLE ERROR file:///app/tns_modules/angular2/src/platform/server/parse5_adapter.js:53:75: STACKTRACE:
CONSOLE ERROR file:///app/tns_modules/angular2/src/platform/server/parse5_adapter.js:53:75: resolvePromise@file:///app/tns_modules/zone.js/dist/zone-node.js:496:41
file:///app/tns_modules/zone.js/dist/zone-node.js:532:32
invokeTask@file:///app/tns_modules/zone.js/dist/zone-node.js:314:43
onInvokeTask@file:///app/tns_modules/angular2/src/core/zone/ng_zone_impl.js:35:51
invokeTask@file:///app/tns_modules/zone.js/dist/zone-node.js:313:55
runTask@file:///app/tns_modules/zone.js/dist/zone-node.js:214:58
drainMicroTaskQueue@file:///app/tns_modules/zone.js/dist/zone-node.js:432:43
promiseReactionJob@[native code]
UIApplicationMain@[native code]
start@file:///app/tns_modules/application/application.js:233:26
file:///app/tns_modules/nativescript-angular/application.js:65:26
ZoneAwarePromise@file:///app/tns_modules/zone.js/dist/zone-node.js:542:38
nativeScriptBootstrap@file:///app/tns_modules/nativescript-angular/application.js:64:23
anonymous@file:///app/main.js:5:36
evaluate@[native code]
moduleEvaluation@[native code]
[native code]
promiseReactionJob@[native code]
CONSOLE ERROR file:///app/tns_modules/zone.js/dist/zone-node.js:419:27: Unhandled Promise rejection: Attempted to assign to readonly property. ; Zone: angular ; Task: Promise.then ; Value: TypeError: Attempted to assign to readonly property.
CONSOLE ERROR file:///app/tns_modules/zone.js/dist/zone-node.js:421:23: Error: Uncaught (in promise): TypeError: Attempted to assign to readonly property.
CONSOLE LOG file:///app/Pages/Home/home.component.js:99:32: scanning complete

More From » angularjs

 Answers
48

The issue is that once you enter the Promise your are in a different context; the this no longer points to the this you thought it did, so you need to save the this into a another variable; some people use that, self or even _this...



So the solution to this issue is;



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

var self = this; // THIS LINE ADDED

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);
}
}).then(function () {
console.log(scanning complete);
self.isScanning = false; // CHANGED!
plusIcon.style.opacity = 1;
}, function (err) {
console.log(error while scanning: + err);
});
self.isScanning = false; // CHANGED!
}
});
}





Update for ES6 method -- You can also use ES6 arrow functions =>
For example you can change the first line to this:



   bluetooth.hasCoarseLocationPermission().then(
(granted) => {


In this case because you used an ES6 arrow function the this will automatically be from the parent scope; and so then you don't need to use the self, _this, or that tricks.



As of NativeScript 2.4 ES6 is supported in both iOS and Android.


[#62534] Thursday, April 14, 2016, 8 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
marinalyssak

Total Points: 637
Total Questions: 101
Total Answers: 94

Location: Morocco
Member since Fri, May 22, 2020
4 Years ago
;