chrome.storageは非同期にご注意
chrome.storage API
Chrome拡張機能の開発で何らかのデータを保存したいとき、chrome.storage APIが使えます。
ブラウザのSessionストレージを使う方法もありますが、chrome.storage APIを使えばBackgroundスクリプトやContentスクリプトからでも簡単にストレージにアクセスできるメリットというメリットがあります。
データを更新してから反映されるまでにラグがある
getメソッドでストレージからデータを取得し、データの一部を更新した後にsetメソッドで更新する。
ということがしたかったのですが、ここで想定してなかったことが起こりました。
何かと言うと、
データを更新した後続の処理で、そのデータを再び取得したときに更新したはずの値が変わっていなかったのです。
具体的にはこんなコードでした。
|
|
Output
value1
なぜこれが起きるか?
結論は、setメソッドをgetメソッドのコールバックの中で行っていたからでした。
言い換えるとsetメソッドが非同期的に実行されていたからです。
期待する挙動は
- getメソッドでデータを取得
- setメソッドでデータを更新
- getメソッドで更新後の値を取得
ですが、実際には
- getメソッドでデータを取得
- getメソッドで更新後(のはずの)の値を取得
- setメソッドでデータを更新
という順番で実行されています。
対策
対策は、
- getメソッドでデータを取得
- setメソッドでデータを更新
この部分を同期的に実行してあげることです。
|
|
Output
value100
getとsetをPromiseでラップしてやって、setメソッドのコールバックでPromiseをresolveしてやるのがみそです。
getメソッドを実行した段階では、まだPromiseがresolveされていないのでawait getAndSetInSync()
でブロックします。
そしてsetメソッドが実行されてデータが更新されて初めて、Promiseがresolveされ次の処理に進みます。
後続の処理で値を確認してみると、きちんと更新されています。
おわり
JavascriptはWeb用の言語ということもあって、非同期処理が前提になっていてコールバックが頻繁に使われているのかなと思います。
非同期処理は複数のことを並列で行えて便利な一方で、こういうトラップもあるので気をつけないとですね。