Search code examples
react-nativeflushasyncstorage

When to use flushGetRequests in AsyncStorage in react-native?


In the documentation of AsyncStorage, I saw that there exists the method flushGetRequests. https://facebook.github.io/react-native/docs/asyncstorage#flushgetrequests

Why does this exist and when should I use it?


Solution

  • I've already posted this in Async Storage's repo, but doing it here, for future references.


    I'm afraid I don't know exact thought behind design process here, but let me try to do it anyway.

    I believe flushGetRequest was implemented to optimize native calls for data, specifically when using callbacks. Like we know, accessing external resources (like DB, reading files) can be "expensive", so devs behind Async Storage tried to make it as performant as possible.

    From the implementation, you can notice that user-facing .multiGet method is not actually calling .multiGet on native side directly. Besides collecting the request and storing it internally (also, removing dup keys on the way), it checks if this._immediate is already set.

    If it's set, then it just proceed with storing keys/requests.

    if it's not set, it fires a setImmediate with flushGetRequests call.

    From React Native docs you can read that

    setImmediate is executed at the end of the current JavaScript execution block, right before sending the batched response back to native.

    What it means that flushGetRequests will be called when the method calling it will finish executing.

    For example:

    getData() {
        AsyncStorage.multiGet(['k1', 'k2'], () => console.log('done'))
    }
    

    flushGetRequests is called after getData has finished executing.

    Where is the optimization, you may ask. What if getData had multiple calls to multiGet?

    getData() {
        AsyncStorage.multiGet(['k1', 'k2'], () => console.log('done'))
        AsyncStorage.multiGet(['k3', 'k4'], () => console.log('done1'))
        AsyncStorage.multiGet(['k5', 'k6'], () => console.log('done2'))
    }
    

    Calling DB/File system every time would be highly inefficient here. So instead, .multiGet gathers all this information and sends it to the native side once this execution is getData, in a single call.

    You don't have to call flushGetRequests yourself - unless you're calling multiple getItem/multiGet sequentially, not asynchronously (using promises), where you need result from one call to make another (one is based on previous one).

    I hope this somehow gets you the answer you're looking for.

    thanks.