コールバックとのやくそく
転職してすぐ入った今の案件のTypescriptはなぜかstrictモードが切られていたり、async/awaitもダメだったりする困ったちゃんです。コンパイルエラー?・・そんなものはない。
ということで非同期処理にはとにかくPromiseを使って書くわけですが、下のコード、どこがおかしいかわかりますか?
class Hello {
private name: string = "";
private remember(name: string): void {
this.name = name;
}
public hi(name: string): void {
new Promise<string>(resolve => {
resolve(name);
}).then(this.remember);
}
}
const h = new Hello();
h.hi("john");
ちなみに以下のようなエラーが出ます。
$ ts-node hello.ts
(node:10336) UnhandledPromiseRejectionWarning: TypeError: Cannot set property 'name' of undefined
at Hello.remember (略)
(node:10336) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:10336) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
this.rememberの中にあるthis.nameで、thisが見つかっていませんね。
このエラー、関数オブジェクトを直接渡さないで無名関数でthen()を書いてたら出ないので「不思議だなー」と思ってしばらく放置してました。
でも、そういえばJavascriptって `function(){}` と `()=>{}` でthisの扱いが違うんですよね。関数オブジェクトを渡した時は前者の扱いで、うまくthisがバインドされないんでしょう。
なので、このエラーは以下のどちらかで解消されます。
(略).then(this.remember.bind(this));
(略).then(name => this.remember(name))
まあ、この例だとエラーが解消されたところで何も表示されないんですが。
こういうエラーに引っかかったら小さなコードを書いて再現してみるのも楽しいですね。
略してないのも置いておきます。それでは。
class Hello {
private name: string = "";
private remember(name: string): void {
this.name = name;
}
public hi(name: string): void {
new Promise<string>(resolve => {
resolve(name);
}).then(this.remember.bind(this));
}
}
const h = new Hello();
h.hi("john");
この記事が気に入ったらサポートをしてみませんか?