web-dev-qa-db-ja.com

同じコマンドが他の場所でも機能するにもかかわらず、読み取り専用プロパティに割り当てようとしましたか?

ボタンを押すとトリガーされるJavascript関数(Angular 2 NativeScriptベースのモバイルアプリ)があります。ボタンを非表示にし、代わりにアクティビティインジケーターを表示し、Bluetoothを実行します。スキャン。完了すると、アクティビティインジケーターがオフになり、元のボタンが表示されます。

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;
            }
        });
}

残念ながら、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
9
George Edwards

問題は、Promiseに入ると、別のコンテキストにいることです。 「this」はあなたが考えていた「this」を指さなくなったので、「this」を別の変数に保存する必要があります。一部の人々は「それ」、「自分」、または「_this」さえ使用します...

したがって、この問題の解決策は次のとおりです。

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!
            }
        });
}

ES6メソッドの更新-ES6矢印関数=>も使用できます。たとえば、最初の行を次のように変更できます。

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

この場合、ES6矢印関数を使用したため、thisは自動的に親スコープから取得されます。したがって、self_this、またはthatのトリックを使用する必要はありません。

NativeScript 2.4 ES6以降は、iOSとAndroidの両方でサポートされています。

11
Nathanael