Promiseの基本の基本を段階的に理解する
以下はこのサイトを見ながらとったメモ
こんな非同期関数を考えた時、どういう問題が生じるかを見ていく
これはPromise以前の話
コールバック関数の話
tsconst double = (data: number, callback: (n: number) => void) => {
setTimeout(() => {
callback(data * 2);
}, Math.random() * 1000);
};
入れ子で使った時に、2つの問題が生じる
ネストが深くなる
ts const nest = () => {
double(2, n => {
console.log(`n1: ${n}`);
double(3, n => {
console.log(`n2: ${n}`);
double(4, n => {
console.log(`n3: ${n}`);
});
});
});
};
実行するタイミングが不定
tsconst order = () => {
double(2, n => {
console.log(`n1: ${n}`);
});
double(3, n => {
console.log(`n2: ${n}`);
});
double(4, n => {
console.log(`n3: ${n}`);
});
};
この結果は n1
, n2
, n3
がどの順に実行されるかは毎回異なる
上に書いた関数をPromiseで書き直す
tsconst doubleP = (data: number) =>
new Promise(callback => {
setTimeout(() => {
callback(data * 2);
}, Math.random() * 1000);
});
Promiseの引数に取る関数のインターフェースについては一旦無視しよう
以下を見ると、上に挙げた2つの問題が解決されていることがわかる
tsconst nestP = () => {
doubleP(2)
.then(n => {
console.log(`n1: ${n}`);
return doubleP(3);
})
.then(n => {
console.log(`n2: ${n}`);
return doubleP(4);
})
.then(n => {
console.log(`n3: ${n}`);
});
};
then
節はチェーンすることができ、一つ前の戻り値を引数として受け取る
TSの型推論を見るとよく分かる
返すものはこのコード例のように毎回新しいPromiseを返すものでも良いし、普通に値を返してもいい
エラー処理
30%の確率で失敗するPromiseを返す関数 doubleE
を定義して結果を見てみる
tsconst doubleE = (data: number) =>
new Promise((f, e) => {
setTimeout(() => {
if (Math.random() < 0.3) {
e(new Error("ERROR!"));
} else {
f(data * 2);
}
}, Math.random() * 1000);
});
const nestE = () => {
doubleE(2)
.then(n => {
console.log(`success: ${n}`);
})
.catch(e => {
console.log(`error: ${e}`);
});
};