Javascript 即使相同的命令在其他地方工作,也试图分配给只读属性?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36657494/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Attempted to assign to readonly property even though same command works elsewhere?
提问by George Edwards
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.
我有一个 Javascript 函数(在基于 Angular 2 NativeScript 的移动应用程序中),它在按下按钮时触发,它应该隐藏按钮并在其位置显示活动指示器,执行蓝牙扫描,完成后关闭活动指示器并显示原始按钮。
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?
不幸的是,该this.isScanning = false;
行抛出了所有这些错误。我做错了什么?
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
回答by Nathanael
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"...
问题是,一旦您进入 Promise,您就会处于不同的上下文中;“this”不再指向您认为它指向的“this”,因此您需要将“this”保存到另一个变量中;有些人使用“that”、“self”甚至“_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:
更新 ES6 方法——您也可以使用 ES6 箭头函数=>
例如,您可以将第一行更改为:
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.
在这种情况下,因为您使用了 ES6 箭头函数,所以this
将自动来自父作用域;所以,你不需要使用self
,_this
或that
技巧。
As of NativeScript 2.4 ES6 is supported in both iOS and Android.
从 NativeScript 2.4 开始,iOS 和 Android 都支持 ES6。