DanLevy.net

Promise の落とし穴

一般的なミスを避ける

Hero image for Promise の落とし穴

Promise は他の値と同じようには動かない

ほとんどの値と違い、直接その値を出力できません:

// Promise では意味がない:
console.log(Promise.resolve(42));
// `.then` インターフェースを使う必要があります:
Promise.resolve(42).then(value => console.log(value));

Promise はミスを警告しない

典型的なミスです。

さまざまな理由で、TC39 は .then.catchnull を渡すことを許容しました。たとえば、.then(null, null) は有効で、チェーン内のその「ステップ」をスキップするという動作が求められます。

この決定の不本意な結果は、ちょっとした手違いで簡単に壊れてしまうことです。

例で確認

次のミニチャレンジを見てみましょう: 以下のどのオプションが console.log に 42 を出力するでしょうか?

// オプション #1:
Promise.resolve(42).then(console.log());
// オプション #2:
Promise.resolve(42).then(console.log);
// オプション #3:
Promise.resolve(42).then(value => console.log(value));
// オプション #4:
Promise.resolve(42)
.then(console.log())
.then(console.log);
答え

正解は #2、#3、#4 です。

なぜでしょうか? .then() に渡された を見てみましょう。

var arg1 = console.log();
var arg2 = console.log;
var arg3 = value => console.log(value);
typeof arg1 === "undefined";
typeof arg2 === "function";
typeof arg3 === "function";

4番目のオプションがどう動くのかまだ気になりますか?

実際には次のように実行されます。

// Option #4 - effectively
Promise.resolve(42)
.then(undefined) // 値に影響はなく、次の `.then(fn)` にそのまま渡される
.then(console.log);