JavaScriptで数値の取り扱いに気をつける

JavaScript

TwitterのAPIを使ってデータ取得し、JavaScript経由で処理をしているときにはまった話です。

特例の文字列に関するTwitterユーザーをユーザー検索APIで叩いて数名の候補を一覧表示して、その中から目的にあった1人のユーザーをリスト化していくという作業をしていました。

使用API:GET users/search
詳細:https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-users-search

Twitterユーザーを一意にする情報としては”screen_name”もしくは”id”
本来の目的からいくと”screen_name”が欲しかったので、この時点で取得した”screen_name”を保存していこうかと考えていましたが、Twitterのアカウントは使われていなければ自由に取得することが可能なため、悪意のある取得であったり、偶然のバッティングが発生することもあります。

これから将来的には、必要性の高い”screen_name”は入替の可能性も出てくるかもしれません。
そこで、書き換えの可能性があり得る”screen_name”だけを取得するよりもユーザー”id”を基準として取得しようと考えたわけです。

やっぱりデータの一意性はID(数値)だね。ということで

JavaScript経由でデータベースに保存しようとしていたので、文字列である”screen_name”にエスケープが必要な文字が入っていると面倒だなとも考えたのも1つです。
(DBに保存するまでデコード、エンコードが繰り返されるので)

ユーザーIDだけ取得してJavaScript経由でPHPスクリプトに渡し、DBに保存する手前で再度API(GET users/lookup)を叩いて”screen_name”を取得するといった流れで作りこみました。

送信ボタンにセットした値はこんな感じです。

すいすいと処理を進めていっていると、DB保存前の段階で”screen_name”が取得できなかった場合のエラー処理コードが表示されました。
とりあえず1件飛ばして進めていると、また同じエラーコードが表示されました。

IDが取得できていなければ先に進めないようにしていたし、ソース表示してもちゃんとIDがデータとして渡されるようになっている。
エラーがでている対象をよく見てみると「IDの桁が多い」ということが分かりました。

JavaScriptは『IEEE754』という規格に従って内部的に数値を『64ビット倍精度』で保管しています。
うまい表現が見つからないですが、処理できる値に限界があるって感じです。

まさかTwitterのIDがそこを超えちゃってるだなんて・・・
数値だけでIDが構成されているので桁数が増えていっているのでしょう。

限界を超えてしまったものをどうするかというと、toFixed(0)を使えばうまく処理できました。

getID.toFixed(0);

こうすれば数値としてPHPスクリプトに渡して再度APIを叩けば正確な”screen_name”を取得することができます。

しかし、IDの構成が数値だけから英数字の組み合わせに変わってしまうと思わぬ落とし穴にまたはまってしまうので、
送信ボタン自体に埋め込む時点で文字列に変更しました。

文字列として最初から処理してしまえばTwitter側の仕様が変わっても問題ありません。
これで解決

JavaScriptで演算するときは数値の変化に気をつけていましたが、受け渡しでも気をつけておかなければならないことを見落としていました。

結論
JavaScriptを使うときの数値は本当に面倒だ