Slide 1

Slide 1 text

ReactNative の AsyncStorage をNode の Repl から操作する @joe_re

Slide 2

Slide 2 text

Who am I? twitter: @joe_re github: @joe­re community: Nishinippori.rb, GraphQL Tokyo Organizer

Slide 3

Slide 3 text

Note Gotanda.js で発表した以下の発表とかぶる部分が多いです。 いらしていた方はすみません https://speakerdeck.com/joere/asyncstoragewonodefalsereplkaracao­ zuo­surutamenitop­leveldeawaitsitairen­sheng­datuta

Slide 4

Slide 4 text

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

Slide 5

Slide 5 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 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

DEMO

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

イメージ図

Slide 11

Slide 11 text

ん?

Slide 12

Slide 12 text

どうしてこうなった

Slide 13

Slide 13 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 14

Slide 14 text

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

Slide 15

Slide 15 text

だるすぎワロた

Slide 16

Slide 16 text

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

Slide 17

Slide 17 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 18

Slide 18 text

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

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

ここまで作った当時(2017/5 月) の情報

Slide 21

Slide 21 text

Chrome のDevTool には top­level await が入った

Slide 22

Slide 22 text

それを受けてNode のRepl にも実装された v10 系から入る予定。試してみたい人はlatest のソースコー ドからビルドすれば今でも使えるはずです https://github.com/nodejs/node/pull/15566

Slide 23

Slide 23 text

というわけでファイル監視は そのうちやめられそう

Slide 24

Slide 24 text

Flow Runtime の採用 https://codemix.github.io/flow­runtime/ compile でassertion をさし挟むことで、 flowtype の型チェックを動的に実行できる 全ての関数呼び出しでassertion を挟むのはパフォーマンス に影響するのでproduction ではoff にすべきだが、 development やtest でon にしておくとより多くの型違反を 検出できる REPL でこれを有効にしたら思ったよりこれぞ型チェックっ て感じになって感動した

Slide 25

Slide 25 text

example > RNAsyncStorage.getItem(1) RuntimeTypeError: key must be a string Expected: string Actual Value: 1 Actual Type: number at RNAsyncStorage.getItem (/Users/noguchimasato/src/async-storage- cli/src/node/RNAsyncStorage.js:25:24) at repl:1:16 at sigintHandlersWrap (vm.js:92:15) at ContextifyScript.Script.runInThisContext (vm.js:42:12) at REPLServer.defaultEval (repl.js:239:29) at bound (domain.js:301:14) at REPLServer.runBound [as eval] (domain.js:314:12) at REPLServer.onLine (repl.js:433:10) at emitOne (events.js:120:20) at REPLServer.emit (events.js:210:7)

Slide 26

Slide 26 text

Extensible AsyncStorage API 基本はAsync Storage のAPI をそのまま提供しているけど、 仕組み上API を組み合わせて新しいAPI を作ることや、 拡張することも可能 現在は dump() と load() のAPI を提供している もっと便利にしていきたいので是非アイディアをください

Slide 27

Slide 27 text

ReactNative のお供にぜひ!

Slide 28

Slide 28 text

ありがとうございました