nuxt-ts day6:TypeScript Deep Dive を読む 2
2020-12-05
# advent

6日目。今日も座学。

https://typescript-jp.gitbook.io

知らなかったことをメモしていく。今日はletから宣言空間まで。

let

var foo = 123;
if (true) {
    var foo = 456;
}
console.log(foo); // 456

JavaScriptにおいてvar変数は関数スコープ(function scope)であり、{は新しい変数スコープ(variable scope)を作成しない。

varの代わりにletを使うと、スコープの外側で定義されているかもしれない変数とは異なる、真にユニークな変数を得ることができる。

let foo = 123;
if (true) {
    let foo = 456;
}
console.log(foo); // 123

const

const の意外なメリット。可読性とメンテナンス性のどちらの面でも良いこと。

// 可読性が低いコードです
if (x > 10) {
}

// このほうがベターです
const maxRows = 10;
if (x > maxRows) {
}

この観点は無かったけど、確かにこれはそうかも。

とりあえずletconstを使っておけば幸せになれるということらしい。

for...of

var someArray = [9, 2, 5];
for (var item of someArray) {
    console.log(item);
}

// ts -> js にトランスパイル //

for (var _i = 0; _i < someArray.length; _i++) {
    var item = someArray[_i];
    console.log(item);
}

これは楽そうだ。

Promise

JSONを読むコードでPromiseを理解する

import fs = require('fs');
function readFileAsync(filename: string): Promise<any> {
    return new Promise((resolve,reject) => {
        fs.readFile(filename,(err,result) => {
            if (err) reject(err);
            else resolve(result);
        });
    });
}

function loadJSONAsync(filename: string): Promise<any> {
    return readFileAsync(filename)
                .then(function (res) {
                    return JSON.parse(res);
                });
}

// 正しいjsonファイル
loadJSONAsync('good.json')
    .then(function (val) { console.log(val); })
    .catch(function (err) {
        console.log('good.json error', err.message); // 呼び出されない
    })

// 存在しないjsonファイル
    .then(function () {
        return loadJSONAsync('absent.json');
    })
    .then(function (val) { console.log(val); }) // 呼び出されない
    .catch(function (err) {
        console.log('absent.json error', err.message);
    })

// 正しくないjsonファイル
    .then(function () {
        return loadJSONAsync('invalid.json');
    })
    .then(function (val) { console.log(val); }) // 呼び出されない
    .catch(function (err) {
        console.log('bad.json error', err.message);
    });

この関数がよりシンプルになった理由は、"loadFile(async)+JSON.parse(sync) => catch"の連結をPromiseチェーンによって行ったためです。また、コールバックは我々ではなくPromiseチェーンによって呼び出されるので、コールバックをtry/catchで囲んでしまう誤りが起きる可能性はありませんでした。

並列制御フロー(Parallel control flow)

複数の非同期処理を実行し、すべてのタスクが終わったタイミングで何らかの処理を行いたいケースについて

// 何らかのデータをサーバから読み込むことを再現する処理
function loadItem(id: number): Promise<{ id: number }> {
    return new Promise((resolve) => {
        console.log('loading item', id);
        setTimeout(() => { // サーバーからのレスポンス遅延を再現
            resolve({ id: id });
        }, 1000);
    });
}

// Promiseチェーン
let item1, item2;
loadItem(1)
    .then((res) => {
        item1 = res;
        return loadItem(2);
    })
    .then((res) => {
        item2 = res;
        console.log('done');
    }); // 全体で 2秒 かかる

// 並列処理
Promise.all([loadItem(1), loadItem(2)])
    .then((res) => {
        [item1, item2] = res;
        console.log('done');
    }); // 全体で 1秒 かかる

これは便利そう!

firestore とかAPIとの疎通で利用できそうだ。

今日はここまで。