1Promise<number> と .then の最小形
Promise<number> は「あとで number が手に入る」という意味の型です。.then に渡した関数の引数 score には、中身の number がそのまま流れてきます。最後の console.log が先に表示されることから、.then の中身は後から実行されると分かります。
// 「あとで number が手に入る」ことを表す型が Promise<number>
function loadScore(): Promise<number> {
return Promise.resolve(80);
}
loadScore().then(function (score) {
// score は number と推論される
console.log(score + 20);
});
console.log("先にこの行が表示される");
2new Promise — 時間のかかる処理を包む
時間のかかる処理を Promise にする基本形が new Promise です。値の用意ができたら resolve(値) を呼ぶと、その値が .then 側へ届きます。戻り値の型を Promise<string> と書いておけば、resolve に渡せる値も string に揃えてチェックされます。
function waitAndGreet(): Promise<string> {
return new Promise(function (resolve) {
setTimeout(function () {
resolve("お待たせしました"); // 100ミリ秒後に値が届く
}, 100);
});
}
console.log("読み込み中...");
waitAndGreet().then(function (greetingText) {
console.log(greetingText);
});
3.then チェーン — 型がリレーされる
.then の中で return した値は、次の .then の引数に流れます。string → number → boolean と、型がリレーのように引き継がれていくのを確認してください。「取得して、加工して、判定する」という実務の処理の流れがそのままこの形になります。
function fetchTitle(): Promise<string> {
return Promise.resolve("TypeScript入門");
}
fetchTitle()
.then(function (title) {
// title は string。return した値が次の .then に流れる
return title.length;
})
.then(function (titleLength) {
// titleLength は number
console.log("タイトルは" + titleLength + "文字");
return titleLength >= 10;
})
.then(function (isLong) {
console.log("長いタイトル? " + isLong); // isLong は boolean
});
4Promise.all — 複数の結果をまとめて待つ
Promise.all は複数の Promise をまとめて待ち、全部そろってから .then を呼びます。結果の配列は渡した順に並ぶことが保証されているので、出力は常に同じになります。1つずつ順番に待つより速く、順序の心配もいりません。
const priceA: Promise<number> = Promise.resolve(480);
const priceB: Promise<number> = Promise.resolve(1200);
const priceC: Promise<number> = Promise.resolve(750);
// 結果の配列は、渡した順に並ぶことが保証される
Promise.all([priceA, priceB, priceC]).then(function (prices) {
console.log(prices);
const total = prices[0] + prices[1] + prices[2];
console.log("合計: " + total + "円");
});
5APIの並行fetch風 — 2つの取得を同時に走らせる
API の並行呼び出しを模した実務寄りの例です。ユーザー名と投稿数の取得を同時に走らせ、両方そろった時点でまとめて表示します。Promise<string> と Promise<number> を混ぜても、結果の型は位置ごとに string と number として正しく推論されます。
function fetchUserName(): Promise<string> {
return new Promise(function (resolve) {
setTimeout(function () { resolve("Taro"); }, 50);
});
}
function fetchPostCount(): Promise<number> {
return new Promise(function (resolve) {
setTimeout(function () { resolve(3); }, 80);
});
}
// 並行で取得し、両方そろってからまとめて出力する
Promise.all([fetchUserName(), fetchPostCount()]).then(function (results) {
console.log(results[0] + "さんの投稿: " + results[1] + "件");
});