Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

joe_re
July 14, 2017

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

五反田.js #8 LT資料

joe_re

July 14, 2017
Tweet

More Decks by joe_re

Other Decks in Technology

Transcript

  1. AsyncStorage
    をNode

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

    View Slide

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

    View Slide

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

    View Slide

  4. 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
    }

    View Slide

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

    View Slide

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

    View Slide

  7. DEMO

    View Slide

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

    View Slide

  9. イメージ図

    View Slide

  10. ん?

    View Slide

  11. どうしてこうなった

    View Slide

  12. 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;
    }

    View Slide

  13. REPL

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

    View Slide

  14. だるすぎワロた

    View Slide

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

    View Slide

  16. 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' );

    View Slide

  17. 将来的にはTop­level await

    できるかも?
    https://github.com/tc39/ecmascript­asyncawait/issues/9

    View Slide

  18. それはそれとしてNode
    のREPL

    例外的に入る可能性も
    https://github.com/nodejs/node/issues/13209

    View Slide

  19. 今回はこのような実装に
    _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;
    }

    View Slide

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

    View Slide

  21. ありがとうございました

    View Slide