1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Iteratorの罠 - コールバックが実行されるタイミング・例外処理

Posted at

今回、Iteratorの.map()等の例外処理に苦戦したので、それを通してIteratorのメソッドの実行タイミングについて書き残します。

この記事ではTypeScriptを使っています。
JavaScriptを使っている人は
頑張って型宣言を外してください。

Iteratorとは?

イテレータープロトコルに準拠するオブジェクトで、色々とメソッドがあって便利です。
TypeScriptではIteratorObject<T>にあたります。
(Iteratorだとイテレータープロトコルになる)

このオブジェクトを返すメソッドが意外と多く、
Array.values()Map.keys()Set.values()など色々とあります。
(こちら.prototypeが省略されています)

失敗するサンプルコード

function addSamaToNames(names: IteratorObject<string>){
    return names.map(e => {
        if(e.toLocaleLowerCase() === "google")
            throw new Error("生理的に無理です");
        return `${e}様`; // 豪華にテンプレートリテラルを使う
    })
}

const names = new Set<string>();
names.add("Microsoft");
names.add("Microsoft");
names.add("Microsoft");
names.add("Qiita");
names.add("Microsoft");
names.add("GitHub");
names.add("Yahoo");
names.add("Google");

try{
    var samas = addSamaToNames(names.values());
}catch{
    // addSamaToNamesでのエラーはここで受け止めたい
    throw new Error("ブロックされました。");
}

console.log(samas.toArray().join(""));

こちら、try-catch文の所で、addSamaToNames
names.mapのコールバックが投げる生理的に無理ですという本音を隠して
例外を投げてほしいのですが、なぜかconsole.logの段階で例外が発生してしまい、
本音が漏れてしまいます。

なぜ失敗する?

なんと、これらイテレーターのメソッドは遅延的に計算するんです。

遅延的というのは、.mapをした時点では実行されず、.toArrayなどで必要になった際計算する仕組みのことです。
これのおかげで無限イテレーターに.mapを使えるそうです。

そのため、addSamaToNamesnames.mapの時点では例外が起こらず、
toArrayの時に計算してしまい他の所で例外を解き放ちます。

対処法

ただ単に、そのメソッド内でtoArray()をするだけです。Array.from()も可。

function addSamaToNames(names: IteratorObject<string>){
    return names.map(e => {
        if(e.toLocaleLowerCase() === "google")
            throw new Error("生理的に無理です");
        return `${e}様`; // 豪華にテンプレートリテラルを使う
    }).toArray();
}

// ~~~

console.log(samas.join(""));

以上です。誰かの役に立てますように。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?