目次
- 概要
- 何にハマったのか?
- 原因
- 解決方法
- 結論
概要
- LWCでプラットフォームイベントを受信して、あれこれしたくなったため、リファレンスを眺めながら実装した。リファレンスに記載されたサンプルコードを入力したのにうまくいかなかった。その後、色々試して解決できたので本記事で記録を残しておこうと思った。
何にハマったのか?
結論
subscribe関数への引数で渡すコールバック関数内で、グローバル変数を参照しようとした際にundefined
にってしまう、、、
経緯踏まえて説明します
- サンプルコードの記載があるリファレンス
- 上記リファレンスから抜粋したコードに独自にコメントを追加(コメント以外はリファレンスのままです)
// プラットフォームイベント登録メソッド
handleSubscribe() {
// プラットフォームイベント受信時にコールされるCallback関数
const messageCallback = function (response) {
console.log('New message received: ', JSON.stringify(response));
// Response contains the payload of the new message received
};
// プラットフォームイベントのサブスク登録メソッド
subscribe(this.channelName, -1, messageCallback).then((response) => {
// Response contains the subscription information on subscribe call
console.log(
'Subscription request sent to: ',
JSON.stringify(response.channel)
);
this.subscription = response;
this.toggleSubscribeButton(true);
});
}
- 上記のコードって、一見して何も問題なさそうに見えて、結構簡単に動かせるんだなぁと思い、コードを貼り付けてデプロイしました
- 実際にプラットフォームイベントを受信することができ、コールバック関数がコールされることを確認しました
- よしよし、では実際のロジックを書いていこうと思いました
- その中でコールバック関数内でグローバル変数で定義している値(this.xxxxで参照する値)を参照しようとした時、なぜかグローバル変数の値が
undefined
になっていました
原因
strictModeでコールバック関数に、アロー関数以外を渡す場合(functionで定義した関数)はthis
の参照先がundefined
になってしまうため
// プラットフォームイベント登録メソッド
handleSubscribe() {
// プラットフォームイベント受信時にコールされるCallback関数
const messageCallback = function (response) {
console.log('New message received: ', JSON.stringify(response));
// Response contains the payload of the new message received
+ console.log(this.xxxx) // <=参照できない。undefinedになる。他では参照できるのに
};
// プラットフォームイベントのサブスク登録メソッド
subscribe(this.channelName, -1, messageCallback).then((response) => {
// Response contains the subscription information on subscribe call
console.log(
'Subscription request sent to: ',
JSON.stringify(response.channel)
);
this.subscription = response;
this.toggleSubscribeButton(true);
});
}
情報を整理していきます。
- jsにはstrict modeというモードがある(MDN)
- 通常strict modeを有効化する場合、 下記のように定義する(上記MDNから抜粋)
// スクリプト全体の厳格モード構文 "use strict"; const v = "こんにちは!厳格モードのスクリプト!";
- strict modeが有効なときは、関数がstrict モードで実行コンテキストに入るときに this 値を明示的に設定しないと、 undefined になる(つまりbindする必要がある。ただしアロー関数は、ソースコード上のコンテキストの this の値が設定される)
- LWCってどうなっているんだろうって調べたら、LWCは暗黙的(use strictの宣言なし)にstrict modeが有効になっているとリファレンスにちゃんとかいてあった。
解決方法
- 上記事実をもとにサンプルコードを見ると、thisの参照先がundefinedになることが理解できた
- どうすればよかったかコードを記載します
-
方法1(thisをbindする)
// プラットフォームイベント登録メソッド handleSubscribe() { // プラットフォームイベント受信時にコールされるCallback関数 const messageCallback = function (response) { console.log('New message received: ', JSON.stringify(response)); // Response contains the payload of the new message received + console.log(this.xxxx) // <=参照できる }; // プラットフォームイベントのサブスク登録メソッド + subscribe(this.channelName, -1, messageCallback.bind(this)).then((response) => { // Response contains the subscription information on subscribe call console.log( 'Subscription request sent to: ', JSON.stringify(response.channel) ); this.subscription = response; this.toggleSubscribeButton(true); }); }
- 方法2(コールバック関数をアロー関数で定義する)
// プラットフォームイベント登録メソッド handleSubscribe() { // プラットフォームイベント受信時にコールされるCallback関数 + const messageCallback = (response) => { console.log('New message received: ', JSON.stringify(response)); // Response contains the payload of the new message received + console.log(this.xxxx) // <=参照できる }; // プラットフォームイベントのサブスク登録メソッド subscribe(this.channelName, -1, messageCallback).then((response) => { // Response contains the subscription information on subscribe call console.log( 'Subscription request sent to: ', JSON.stringify(response.channel) ); this.subscription = response; this.toggleSubscribeButton(true); }); }
-
結論
- リファレンスはしっかり読みましょう
- 1個のリファレンスだけを信用するのではなく、関連するリファレンスも読み、照らし合わせて情報を整理しましょう
- 機械は嘘つかない
色々学べました。この記事が誰かのためになれば幸いです。