Slide 1

Slide 1 text

AsyncStorage をNode の REPL から操作するために Top­level でawait したい 人生だった @joe_re

Slide 2

Slide 2 text

Who am I? twitter: @joe_re github: @joe­re working in freee.K.K

Slide 3

Slide 3 text

What is AsyncStorage? ReactNative の標準で搭載されたkey­value ストレージ 気軽にReactNative に永続化したいデータを持つときに便利 ReactNative で使えるLocalStorage みたいなもの

Slide 4

Slide 4 text

Example Persisting date: try { await AsyncStorage.setItem('@MySuperStore:key', 'I like to save it.'); } catch (error) { // Error saving data } Fetching date: try { const value = await AsyncStorage.getItem('@MySuperStore:key'); if (value !== null){ // We have data!! console.log(value); } } catch (error) { // Error retrieving data }

Slide 5

Slide 5 text

AsyncStorage をNode のREPL から操作したいという欲望 AsyncStorage には外部から叩けるAPI は用意されていない 開発中にデータ構造が変わったときにアプリケーションに データを修正するためのコードを書くのは面倒 ちゃんとデータが保存されたかどうか確かめるのも面倒 REPL からAsyncStorage のAPI を叩きたい (rails console みたいなイメージ)

Slide 6

Slide 6 text

作った https://github.com/joe­re/async­storage­repl

Slide 7

Slide 7 text

DEMO

Slide 8

Slide 8 text

仕組み Node とReactNative との通信はWebsocket で行う REPL 起動時に子プロセスとしてReactNative アプリケーションと通信するWSS を立ち上げる REPL とWSS はプロセス間通信を行う

Slide 9

Slide 9 text

イメージ図

Slide 10

Slide 10 text

ん?

Slide 11

Slide 11 text

どうしてこうなった

Slide 12

Slide 12 text

Node.js ではTop Level で非同期処理の 結果を扱えない 人類はES2017 よりasync/await を獲得したが、 await はasync function の中でしか使えない // ng function request { const response = await fetch( '/data.json' ); const json = await response.json(); const result = await hydrateSomehow(json); return result; } // ok function async request { const response = await fetch( '/data.json' ); const json = await response.json(); const result = await hydrateSomehow(json); return result; }

Slide 13

Slide 13 text

REPL で Promise オブジェクトを 扱おうとすると.. > let out = null; > promiseObj.then((res) => { out = res }); > out // finally available here

Slide 14

Slide 14 text

だるすぎワロた

Slide 15

Slide 15 text

Top­level await is a footgun https://gist.github.com/Rich­ Harris/0b6f317657f5167663b493c722647221 Top­level のawait を許すと1 つの依存を解決するだけでも、 その先の関係のない処理まで止めざるを得ない await は直列を強要するので、ネットワークを介した処理の 並列化ができない

Slide 16

Slide 16 text

Example(borrow from Harris) // main.js import './foo.js'; import './bar.js'; // foo.js await delay( Math.random() * 1000 ); console.log( 'foo happened' ); // bar.js await delay( Math.random() * 1000 ); console.log( 'bar happened' );

Slide 17

Slide 17 text

将来的にはTop­level await が できるかも? https://github.com/tc39/ecmascript­asyncawait/issues/9

Slide 18

Slide 18 text

それはそれとしてNode のREPL に 例外的に入る可能性も https://github.com/nodejs/node/issues/13209

Slide 19

Slide 19 text

今回はこのような実装に _resolveMessageFromRN(fileName) { let json = {}; let received = false; for (let i = 0; i < this.timeout; i++) { sleep.msleep(100); const fileContent = fs.readFileSync(fileName, 'utf8'); if (fileContent) { json = JSON.parse(fileContent); delete this.que[Number(json.queId)]; received = true; break; } sleep.msleep(900); } fs.unlinkSync(fileName); if (!received) { throw new Error("can't receive response from ReactNative Application"); } if (json.error === 1) { throw new Error(json.message); } return json.result; }

Slide 20

Slide 20 text

そうは言っても結構便利です。 ReactNative のお供にぜひ!

Slide 21

Slide 21 text

ありがとうございました